doorkeeper 5.3.0 → 5.4.0.rc1

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +0 -14
  3. data/CHANGELOG.md +44 -1
  4. data/Dangerfile +7 -7
  5. data/Dockerfile +2 -2
  6. data/Gemfile +9 -9
  7. data/README.md +6 -4
  8. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  11. data/app/controllers/doorkeeper/tokens_controller.rb +57 -20
  12. data/app/views/doorkeeper/applications/show.html.erb +19 -2
  13. data/bin/console +14 -0
  14. data/config/locales/en.yml +3 -1
  15. data/doorkeeper.gemspec +1 -1
  16. data/gemfiles/rails_5_0.gemfile +8 -7
  17. data/gemfiles/rails_5_1.gemfile +8 -7
  18. data/gemfiles/rails_5_2.gemfile +8 -7
  19. data/gemfiles/rails_6_0.gemfile +8 -7
  20. data/gemfiles/rails_master.gemfile +8 -7
  21. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  22. data/lib/doorkeeper/config/option.rb +28 -14
  23. data/lib/doorkeeper/config.rb +41 -17
  24. data/lib/doorkeeper/grape/helpers.rb +1 -1
  25. data/lib/doorkeeper/models/access_grant_mixin.rb +9 -11
  26. data/lib/doorkeeper/models/access_token_mixin.rb +102 -42
  27. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  28. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  29. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  30. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  31. data/lib/doorkeeper/oauth/authorization/code.rb +14 -5
  32. data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
  33. data/lib/doorkeeper/oauth/authorization/token.rb +7 -11
  34. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  35. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
  36. data/lib/doorkeeper/oauth/base_request.rb +11 -19
  37. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  38. data/lib/doorkeeper/oauth/client.rb +1 -1
  39. data/lib/doorkeeper/oauth/client_credentials/creator.rb +25 -7
  40. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  41. data/lib/doorkeeper/oauth/client_credentials/validator.rb +1 -1
  42. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  43. data/lib/doorkeeper/oauth/code_request.rb +1 -1
  44. data/lib/doorkeeper/oauth/code_response.rb +6 -2
  45. data/lib/doorkeeper/oauth/error_response.rb +2 -4
  46. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
  47. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  48. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  49. data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -5
  50. data/lib/doorkeeper/oauth/pre_authorization.rb +32 -27
  51. data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
  52. data/lib/doorkeeper/oauth/token.rb +1 -1
  53. data/lib/doorkeeper/oauth/token_introspection.rb +3 -3
  54. data/lib/doorkeeper/oauth/token_request.rb +2 -2
  55. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  56. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +7 -2
  57. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +6 -2
  58. data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -2
  59. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  60. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  61. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  62. data/lib/doorkeeper/rails/routes.rb +13 -17
  63. data/lib/doorkeeper/request/strategy.rb +2 -2
  64. data/lib/doorkeeper/server.rb +3 -3
  65. data/lib/doorkeeper/version.rb +2 -2
  66. data/lib/doorkeeper.rb +106 -79
  67. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  68. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  69. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
  70. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  71. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  72. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  73. data/lib/generators/doorkeeper/templates/initializer.rb +47 -3
  74. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -0
  75. data/spec/controllers/applications_controller_spec.rb +2 -2
  76. data/spec/controllers/authorizations_controller_spec.rb +165 -30
  77. data/spec/controllers/tokens_controller_spec.rb +6 -5
  78. data/spec/dummy/app/helpers/application_helper.rb +1 -1
  79. data/spec/dummy/app/models/user.rb +5 -1
  80. data/spec/dummy/config/application.rb +6 -4
  81. data/spec/dummy/config/boot.rb +4 -4
  82. data/spec/dummy/config/environment.rb +1 -1
  83. data/spec/dummy/config/routes.rb +4 -4
  84. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +2 -2
  85. data/spec/dummy/db/schema.rb +3 -1
  86. data/spec/factories.rb +1 -1
  87. data/spec/generators/enable_polymorphic_resource_owner_generator_spec.rb +47 -0
  88. data/spec/lib/config_spec.rb +30 -11
  89. data/spec/lib/models/revocable_spec.rb +2 -3
  90. data/spec/lib/models/scopes_spec.rb +8 -0
  91. data/spec/lib/oauth/authorization_code_request_spec.rb +25 -15
  92. data/spec/lib/oauth/base_request_spec.rb +6 -20
  93. data/spec/lib/oauth/client_credentials/creator_spec.rb +90 -89
  94. data/spec/lib/oauth/client_credentials/issuer_spec.rb +84 -86
  95. data/spec/lib/oauth/client_credentials/validation_spec.rb +38 -40
  96. data/spec/lib/oauth/client_credentials_request_spec.rb +5 -4
  97. data/spec/lib/oauth/code_request_spec.rb +1 -1
  98. data/spec/lib/oauth/code_response_spec.rb +5 -1
  99. data/spec/lib/oauth/error_response_spec.rb +1 -1
  100. data/spec/lib/oauth/password_access_token_request_spec.rb +24 -13
  101. data/spec/lib/oauth/pre_authorization_spec.rb +13 -18
  102. data/spec/lib/oauth/refresh_token_request_spec.rb +19 -30
  103. data/spec/lib/oauth/token_request_spec.rb +14 -7
  104. data/spec/lib/option_spec.rb +51 -0
  105. data/spec/lib/stale_records_cleaner_spec.rb +18 -5
  106. data/spec/models/doorkeeper/access_grant_spec.rb +18 -4
  107. data/spec/models/doorkeeper/access_token_spec.rb +507 -479
  108. data/spec/models/doorkeeper/application_spec.rb +338 -300
  109. data/spec/requests/endpoints/token_spec.rb +5 -1
  110. data/spec/requests/flows/authorization_code_errors_spec.rb +4 -1
  111. data/spec/requests/flows/authorization_code_spec.rb +6 -1
  112. data/spec/requests/flows/client_credentials_spec.rb +41 -0
  113. data/spec/requests/flows/refresh_token_spec.rb +16 -8
  114. data/spec/requests/flows/revoke_token_spec.rb +143 -104
  115. data/spec/support/helpers/access_token_request_helper.rb +1 -0
  116. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  117. data/spec/support/helpers/config_helper.rb +1 -1
  118. data/spec/support/shared/controllers_shared_context.rb +2 -2
  119. data/spec/support/shared/models_shared_examples.rb +6 -4
  120. metadata +15 -4
@@ -3,401 +3,439 @@
3
3
  require "spec_helper"
4
4
  require "bcrypt"
5
5
 
6
- module Doorkeeper
7
- describe Application do
8
- let(:clazz) { Doorkeeper::Application }
9
- let(:require_owner) { Doorkeeper.configuration.instance_variable_set("@confirm_application_owner", true) }
10
- let(:unset_require_owner) { Doorkeeper.configuration.instance_variable_set("@confirm_application_owner", false) }
11
- let(:new_application) { FactoryBot.build(:application) }
6
+ describe Doorkeeper::Application do
7
+ let(:require_owner) { Doorkeeper.config.instance_variable_set("@confirm_application_owner", true) }
8
+ let(:unset_require_owner) { Doorkeeper.config.instance_variable_set("@confirm_application_owner", false) }
9
+ let(:new_application) { FactoryBot.build(:application) }
12
10
 
13
- let(:uid) { SecureRandom.hex(8) }
14
- let(:secret) { SecureRandom.hex(8) }
11
+ let(:uid) { SecureRandom.hex(8) }
12
+ let(:secret) { SecureRandom.hex(8) }
15
13
 
16
- it "is invalid without a name" do
17
- new_application.name = nil
18
- expect(new_application).not_to be_valid
19
- end
14
+ it "is invalid without a name" do
15
+ new_application.name = nil
16
+ expect(new_application).not_to be_valid
17
+ end
20
18
 
21
- it "is invalid without determining confidentiality" do
22
- new_application.confidential = nil
23
- expect(new_application).not_to be_valid
24
- end
19
+ it "is invalid without determining confidentiality" do
20
+ new_application.confidential = nil
21
+ expect(new_application).not_to be_valid
22
+ end
25
23
 
26
- it "generates uid on create" do
27
- expect(new_application.uid).to be_nil
28
- new_application.save
29
- expect(new_application.uid).not_to be_nil
30
- end
24
+ it "generates uid on create" do
25
+ expect(new_application.uid).to be_nil
26
+ new_application.save
27
+ expect(new_application.uid).not_to be_nil
28
+ end
31
29
 
32
- it "generates uid on create if an empty string" do
33
- new_application.uid = ""
34
- new_application.save
35
- expect(new_application.uid).not_to be_blank
36
- end
30
+ it "generates uid on create if an empty string" do
31
+ new_application.uid = ""
32
+ new_application.save
33
+ expect(new_application.uid).not_to be_blank
34
+ end
37
35
 
38
- it "generates uid on create unless one is set" do
39
- new_application.uid = uid
40
- new_application.save
41
- expect(new_application.uid).to eq(uid)
42
- end
36
+ it "generates uid on create unless one is set" do
37
+ new_application.uid = uid
38
+ new_application.save
39
+ expect(new_application.uid).to eq(uid)
40
+ end
43
41
 
44
- it "is invalid without uid" do
45
- new_application.save
46
- new_application.uid = nil
47
- expect(new_application).not_to be_valid
48
- end
42
+ it "is invalid without uid" do
43
+ new_application.save
44
+ new_application.uid = nil
45
+ expect(new_application).not_to be_valid
46
+ end
49
47
 
50
- it "checks uniqueness of uid" do
51
- app1 = FactoryBot.create(:application)
52
- app2 = FactoryBot.create(:application)
53
- app2.uid = app1.uid
54
- expect(app2).not_to be_valid
55
- end
48
+ it "checks uniqueness of uid" do
49
+ app1 = FactoryBot.create(:application)
50
+ app2 = FactoryBot.create(:application)
51
+ app2.uid = app1.uid
52
+ expect(app2).not_to be_valid
53
+ end
56
54
 
57
- it "expects database to throw an error when uids are the same" do
58
- app1 = FactoryBot.create(:application)
59
- app2 = FactoryBot.create(:application)
60
- app2.uid = app1.uid
61
- expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
62
- end
55
+ it "expects database to throw an error when uids are the same" do
56
+ app1 = FactoryBot.create(:application)
57
+ app2 = FactoryBot.create(:application)
58
+ app2.uid = app1.uid
59
+ expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
60
+ end
63
61
 
64
- it "generate secret on create" do
65
- expect(new_application.secret).to be_nil
66
- new_application.save
67
- expect(new_application.secret).not_to be_nil
68
- end
62
+ it "generate secret on create" do
63
+ expect(new_application.secret).to be_nil
64
+ new_application.save
65
+ expect(new_application.secret).not_to be_nil
66
+ end
69
67
 
70
- it "generate secret on create if is blank string" do
71
- new_application.secret = ""
72
- new_application.save
73
- expect(new_application.secret).not_to be_blank
74
- end
68
+ it "generate secret on create if is blank string" do
69
+ new_application.secret = ""
70
+ new_application.save
71
+ expect(new_application.secret).not_to be_blank
72
+ end
75
73
 
76
- it "generate secret on create unless one is set" do
77
- new_application.secret = secret
78
- new_application.save
79
- expect(new_application.secret).to eq(secret)
80
- end
74
+ it "generate secret on create unless one is set" do
75
+ new_application.secret = secret
76
+ new_application.save
77
+ expect(new_application.secret).to eq(secret)
78
+ end
81
79
 
82
- it "is invalid without secret" do
83
- new_application.save
84
- new_application.secret = nil
85
- expect(new_application).not_to be_valid
86
- end
80
+ it "is invalid without secret" do
81
+ new_application.save
82
+ new_application.secret = nil
83
+ expect(new_application).not_to be_valid
84
+ end
87
85
 
88
- context "application_owner is enabled" do
89
- before do
90
- Doorkeeper.configure do
91
- orm DOORKEEPER_ORM
92
- enable_application_owner
93
- end
86
+ context "application_owner is enabled" do
87
+ before do
88
+ Doorkeeper.configure do
89
+ orm DOORKEEPER_ORM
90
+ enable_application_owner
94
91
  end
92
+ end
95
93
 
96
- context "application owner is not required" do
97
- before(:each) do
98
- unset_require_owner
99
- end
94
+ context "application owner is not required" do
95
+ before(:each) do
96
+ unset_require_owner
97
+ end
100
98
 
101
- it "is valid given valid attributes" do
102
- expect(new_application).to be_valid
103
- end
99
+ it "is valid given valid attributes" do
100
+ expect(new_application).to be_valid
104
101
  end
102
+ end
105
103
 
106
- context "application owner is required" do
107
- before(:each) do
108
- require_owner
109
- @owner = FactoryBot.build_stubbed(:doorkeeper_testing_user)
110
- end
104
+ context "application owner is required" do
105
+ before(:each) do
106
+ require_owner
107
+ @owner = FactoryBot.build_stubbed(:doorkeeper_testing_user)
108
+ end
111
109
 
112
- it "is invalid without an owner" do
113
- expect(new_application).not_to be_valid
114
- end
110
+ it "is invalid without an owner" do
111
+ expect(new_application).not_to be_valid
112
+ end
115
113
 
116
- it "is valid with an owner" do
117
- new_application.owner = @owner
118
- expect(new_application).to be_valid
119
- end
114
+ it "is valid with an owner" do
115
+ new_application.owner = @owner
116
+ expect(new_application).to be_valid
120
117
  end
121
118
  end
119
+ end
122
120
 
123
- context "redirect URI" do
124
- context "when grant flows allow blank redirect URI" do
125
- before do
126
- Doorkeeper.configure do
127
- grant_flows %w[password client_credentials]
128
- end
121
+ context "redirect URI" do
122
+ context "when grant flows allow blank redirect URI" do
123
+ before do
124
+ Doorkeeper.configure do
125
+ grant_flows %w[password client_credentials]
129
126
  end
127
+ end
130
128
 
131
- it "is valid without redirect_uri" do
132
- new_application.save
133
- new_application.redirect_uri = nil
134
- expect(new_application).to be_valid
135
- end
129
+ it "is valid without redirect_uri" do
130
+ new_application.save
131
+ new_application.redirect_uri = nil
132
+ expect(new_application).to be_valid
136
133
  end
134
+ end
137
135
 
138
- context "when grant flows require redirect URI" do
139
- before do
140
- Doorkeeper.configure do
141
- grant_flows %w[password client_credentials authorization_code]
142
- end
136
+ context "when grant flows require redirect URI" do
137
+ before do
138
+ Doorkeeper.configure do
139
+ grant_flows %w[password client_credentials authorization_code]
143
140
  end
141
+ end
144
142
 
145
- it "is invalid without redirect_uri" do
146
- new_application.save
147
- new_application.redirect_uri = nil
148
- expect(new_application).not_to be_valid
149
- end
143
+ it "is invalid without redirect_uri" do
144
+ new_application.save
145
+ new_application.redirect_uri = nil
146
+ expect(new_application).not_to be_valid
150
147
  end
148
+ end
151
149
 
152
- context "when blank URI option disabled" do
153
- before do
154
- Doorkeeper.configure do
155
- grant_flows %w[password client_credentials]
156
- allow_blank_redirect_uri false
157
- end
150
+ context "when blank URI option disabled" do
151
+ before do
152
+ Doorkeeper.configure do
153
+ grant_flows %w[password client_credentials]
154
+ allow_blank_redirect_uri false
158
155
  end
156
+ end
159
157
 
160
- it "is invalid without redirect_uri" do
161
- new_application.save
162
- new_application.redirect_uri = nil
163
- expect(new_application).not_to be_valid
164
- end
158
+ it "is invalid without redirect_uri" do
159
+ new_application.save
160
+ new_application.redirect_uri = nil
161
+ expect(new_application).not_to be_valid
165
162
  end
166
163
  end
164
+ end
167
165
 
168
- context "with hashing enabled" do
169
- include_context "with application hashing enabled"
170
- let(:app) { FactoryBot.create :application }
171
- let(:default_strategy) { Doorkeeper::SecretStoring::Sha256Hash }
166
+ context "with hashing enabled" do
167
+ include_context "with application hashing enabled"
168
+ let(:app) { FactoryBot.create :application }
169
+ let(:default_strategy) { Doorkeeper::SecretStoring::Sha256Hash }
172
170
 
173
- it "uses SHA256 to avoid additional dependencies" do
174
- # Ensure token was generated
175
- app.validate
176
- expect(app.secret).to eq(default_strategy.transform_secret(app.plaintext_secret))
177
- end
171
+ it "uses SHA256 to avoid additional dependencies" do
172
+ # Ensure token was generated
173
+ app.validate
174
+ expect(app.secret).to eq(default_strategy.transform_secret(app.plaintext_secret))
175
+ end
178
176
 
179
- context "when bcrypt strategy is configured" do
180
- # In this text context, we have bcrypt loaded so `bcrypt_present?`
181
- # will always be true
182
- before do
183
- Doorkeeper.configure do
184
- hash_application_secrets using: "Doorkeeper::SecretStoring::BCrypt"
185
- end
177
+ context "when bcrypt strategy is configured" do
178
+ # In this text context, we have bcrypt loaded so `bcrypt_present?`
179
+ # will always be true
180
+ before do
181
+ Doorkeeper.configure do
182
+ hash_application_secrets using: "Doorkeeper::SecretStoring::BCrypt"
186
183
  end
184
+ end
187
185
 
188
- it "holds a volatile plaintext and BCrypt secret" do
189
- expect(app.secret_strategy).to eq Doorkeeper::SecretStoring::BCrypt
190
- expect(app.plaintext_secret).to be_a(String)
191
- expect(app.secret).not_to eq(app.plaintext_secret)
192
- expect { ::BCrypt::Password.create(app.secret) }.not_to raise_error
193
- end
186
+ it "holds a volatile plaintext and BCrypt secret" do
187
+ expect(app.secret_strategy).to eq Doorkeeper::SecretStoring::BCrypt
188
+ expect(app.plaintext_secret).to be_a(String)
189
+ expect(app.secret).not_to eq(app.plaintext_secret)
190
+ expect { ::BCrypt::Password.create(app.secret) }.not_to raise_error
194
191
  end
192
+ end
195
193
 
196
- it "does not fallback to plain lookup by default" do
197
- lookup = clazz.by_uid_and_secret(app.uid, app.secret)
198
- expect(lookup).to eq(nil)
194
+ it "does not fallback to plain lookup by default" do
195
+ lookup = described_class.by_uid_and_secret(app.uid, app.secret)
196
+ expect(lookup).to eq(nil)
199
197
 
200
- lookup = clazz.by_uid_and_secret(app.uid, app.plaintext_secret)
201
- expect(lookup).to eq(app)
202
- end
198
+ lookup = described_class.by_uid_and_secret(app.uid, app.plaintext_secret)
199
+ expect(lookup).to eq(app)
200
+ end
203
201
 
204
- context "with fallback enabled" do
205
- include_context "with token hashing and fallback lookup enabled"
202
+ context "with fallback enabled" do
203
+ include_context "with token hashing and fallback lookup enabled"
206
204
 
207
- it "provides plain and hashed lookup" do
208
- lookup = clazz.by_uid_and_secret(app.uid, app.secret)
209
- expect(lookup).to eq(app)
205
+ it "provides plain and hashed lookup" do
206
+ lookup = described_class.by_uid_and_secret(app.uid, app.secret)
207
+ expect(lookup).to eq(app)
210
208
 
211
- lookup = clazz.by_uid_and_secret(app.uid, app.plaintext_secret)
212
- expect(lookup).to eq(app)
213
- end
209
+ lookup = described_class.by_uid_and_secret(app.uid, app.plaintext_secret)
210
+ expect(lookup).to eq(app)
214
211
  end
212
+ end
215
213
 
216
- it "does not provide access to secret after loading" do
217
- lookup = clazz.by_uid_and_secret(app.uid, app.plaintext_secret)
218
- expect(lookup.plaintext_secret).to be_nil
219
- end
214
+ it "does not provide access to secret after loading" do
215
+ lookup = described_class.by_uid_and_secret(app.uid, app.plaintext_secret)
216
+ expect(lookup.plaintext_secret).to be_nil
220
217
  end
218
+ end
221
219
 
222
- describe "destroy related models on cascade" do
223
- before(:each) do
224
- new_application.save
225
- end
220
+ describe "destroy related models on cascade" do
221
+ before(:each) do
222
+ new_application.save
223
+ end
226
224
 
227
- it "should destroy its access grants" do
228
- FactoryBot.create(:access_grant, application: new_application)
229
- expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
230
- end
225
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
231
226
 
232
- it "should destroy its access tokens" do
233
- FactoryBot.create(:access_token, application: new_application)
234
- FactoryBot.create(:access_token, application: new_application, revoked_at: Time.now.utc)
235
- expect do
236
- new_application.destroy
237
- end.to change { Doorkeeper::AccessToken.count }.by(-2)
238
- end
227
+ it "should destroy its access grants" do
228
+ FactoryBot.create(
229
+ :access_grant,
230
+ application: new_application,
231
+ resource_owner_id: resource_owner.id,
232
+ resource_owner_type: resource_owner.class.name,
233
+ )
234
+
235
+ expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
239
236
  end
240
237
 
241
- describe "#ordered_by" do
242
- let(:applications) { FactoryBot.create_list(:application, 5) }
238
+ it "should destroy its access tokens" do
239
+ FactoryBot.create(:access_token, application: new_application)
240
+ FactoryBot.create(:access_token, application: new_application, revoked_at: Time.now.utc)
241
+ expect do
242
+ new_application.destroy
243
+ end.to change { Doorkeeper::AccessToken.count }.by(-2)
244
+ end
245
+ end
243
246
 
244
- context "when a direction is not specified" do
245
- it "calls order with a default order of asc" do
246
- names = applications.map(&:name).sort
247
- expect(Application.ordered_by(:name).map(&:name)).to eq(names)
248
- end
247
+ describe "#ordered_by" do
248
+ let(:applications) { FactoryBot.create_list(:application, 5) }
249
+
250
+ context "when a direction is not specified" do
251
+ it "calls order with a default order of asc" do
252
+ names = applications.map(&:name).sort
253
+ expect(described_class.ordered_by(:name).map(&:name)).to eq(names)
249
254
  end
255
+ end
250
256
 
251
- context "when a direction is specified" do
252
- it "calls order with specified direction" do
253
- names = applications.map(&:name).sort.reverse
254
- expect(Application.ordered_by(:name, :desc).map(&:name)).to eq(names)
255
- end
257
+ context "when a direction is specified" do
258
+ it "calls order with specified direction" do
259
+ names = applications.map(&:name).sort.reverse
260
+ expect(described_class.ordered_by(:name, :desc).map(&:name)).to eq(names)
256
261
  end
257
262
  end
263
+ end
258
264
 
259
- describe "#redirect_uri=" do
260
- context "when array of valid redirect_uris" do
261
- it "should join by newline" do
262
- new_application.redirect_uri = ["http://localhost/callback1", "http://localhost/callback2"]
263
- expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
264
- end
265
+ describe "#redirect_uri=" do
266
+ context "when array of valid redirect_uris" do
267
+ it "should join by newline" do
268
+ new_application.redirect_uri = ["http://localhost/callback1", "http://localhost/callback2"]
269
+ expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
265
270
  end
266
- context "when string of valid redirect_uris" do
267
- it "should store as-is" do
268
- new_application.redirect_uri = "http://localhost/callback1\nhttp://localhost/callback2"
269
- expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
270
- end
271
+ end
272
+ context "when string of valid redirect_uris" do
273
+ it "should store as-is" do
274
+ new_application.redirect_uri = "http://localhost/callback1\nhttp://localhost/callback2"
275
+ expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
271
276
  end
272
277
  end
278
+ end
273
279
 
274
- describe "#renew_secret" do
275
- let(:app) { FactoryBot.create :application }
280
+ describe "#renew_secret" do
281
+ let(:app) { FactoryBot.create :application }
276
282
 
277
- it "should generate a new secret" do
278
- old_secret = app.secret
279
- app.renew_secret
280
- expect(old_secret).not_to eq(app.secret)
281
- end
283
+ it "should generate a new secret" do
284
+ old_secret = app.secret
285
+ app.renew_secret
286
+ expect(old_secret).not_to eq(app.secret)
282
287
  end
288
+ end
283
289
 
284
- describe "#authorized_for" do
285
- let(:resource_owner) { double(:resource_owner, id: 10) }
290
+ describe "#authorized_for" do
291
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
292
+ let(:other_resource_owner) { FactoryBot.create(:resource_owner) }
286
293
 
287
- it "is empty if the application is not authorized for anyone" do
288
- expect(Application.authorized_for(resource_owner)).to be_empty
289
- end
294
+ it "is empty if the application is not authorized for anyone" do
295
+ expect(described_class.authorized_for(resource_owner)).to be_empty
296
+ end
290
297
 
291
- it "returns only application for a specific resource owner" do
292
- FactoryBot.create(:access_token, resource_owner_id: resource_owner.id + 1)
293
- token = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
294
- expect(Application.authorized_for(resource_owner)).to eq([token.application])
295
- end
298
+ it "returns only application for a specific resource owner" do
299
+ FactoryBot.create(
300
+ :access_token,
301
+ resource_owner_id: other_resource_owner.id,
302
+ resource_owner_type: other_resource_owner.class.name,
303
+ )
304
+ token = FactoryBot.create(
305
+ :access_token,
306
+ resource_owner_id: resource_owner.id,
307
+ resource_owner_type: resource_owner.class.name,
308
+ )
309
+ expect(described_class.authorized_for(resource_owner)).to eq([token.application])
310
+ end
296
311
 
297
- it "excludes revoked tokens" do
298
- FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, revoked_at: 2.days.ago)
299
- expect(Application.authorized_for(resource_owner)).to be_empty
300
- end
312
+ it "excludes revoked tokens" do
313
+ FactoryBot.create(
314
+ :access_token,
315
+ resource_owner_id: resource_owner.id,
316
+ resource_owner_type: resource_owner.class.name,
317
+ revoked_at: 2.days.ago,
318
+ )
319
+ expect(described_class.authorized_for(resource_owner)).to be_empty
320
+ end
301
321
 
302
- it "returns all applications that have been authorized" do
303
- token1 = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
304
- token2 = FactoryBot.create(:access_token, resource_owner_id: resource_owner.id)
305
- expect(Application.authorized_for(resource_owner)).to eq([token1.application, token2.application])
306
- end
322
+ it "returns all applications that have been authorized" do
323
+ token1 = FactoryBot.create(
324
+ :access_token,
325
+ resource_owner_id: resource_owner.id,
326
+ resource_owner_type: resource_owner.class.name,
327
+ )
328
+ token2 = FactoryBot.create(
329
+ :access_token,
330
+ resource_owner_id: resource_owner.id,
331
+ resource_owner_type: resource_owner.class.name,
332
+ )
333
+ expect(described_class.authorized_for(resource_owner))
334
+ .to eq([token1.application, token2.application])
335
+ end
307
336
 
308
- it "returns only one application even if it has been authorized twice" do
309
- application = FactoryBot.create(:application)
310
- FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, application: application)
311
- FactoryBot.create(:access_token, resource_owner_id: resource_owner.id, application: application)
312
- expect(Application.authorized_for(resource_owner)).to eq([application])
313
- end
337
+ it "returns only one application even if it has been authorized twice" do
338
+ application = FactoryBot.create(:application)
339
+ FactoryBot.create(
340
+ :access_token,
341
+ resource_owner_id: resource_owner.id,
342
+ resource_owner_type: resource_owner.class.name,
343
+ application: application,
344
+ )
345
+ FactoryBot.create(
346
+ :access_token,
347
+ resource_owner_id: resource_owner.id,
348
+ resource_owner_type: resource_owner.class.name,
349
+ application: application,
350
+ )
351
+ expect(described_class.authorized_for(resource_owner)).to eq([application])
314
352
  end
353
+ end
315
354
 
316
- describe "#revoke_tokens_and_grants_for" do
317
- it "revokes all access tokens and access grants" do
318
- application_id = 42
319
- resource_owner = double
320
- expect(Doorkeeper::AccessToken)
321
- .to receive(:revoke_all_for).with(application_id, resource_owner)
322
- expect(Doorkeeper::AccessGrant)
323
- .to receive(:revoke_all_for).with(application_id, resource_owner)
355
+ describe "#revoke_tokens_and_grants_for" do
356
+ it "revokes all access tokens and access grants" do
357
+ application_id = 42
358
+ resource_owner = double
359
+ expect(Doorkeeper::AccessToken)
360
+ .to receive(:revoke_all_for).with(application_id, resource_owner)
361
+ expect(Doorkeeper::AccessGrant)
362
+ .to receive(:revoke_all_for).with(application_id, resource_owner)
324
363
 
325
- Application.revoke_tokens_and_grants_for(application_id, resource_owner)
326
- end
364
+ described_class.revoke_tokens_and_grants_for(application_id, resource_owner)
327
365
  end
366
+ end
328
367
 
329
- describe "#by_uid_and_secret" do
330
- context "when application is private/confidential" do
331
- it "finds the application via uid/secret" do
368
+ describe "#by_uid_and_secret" do
369
+ context "when application is private/confidential" do
370
+ it "finds the application via uid/secret" do
371
+ app = FactoryBot.create :application
372
+ authenticated = described_class.by_uid_and_secret(app.uid, app.secret)
373
+ expect(authenticated).to eq(app)
374
+ end
375
+ context "when secret is wrong" do
376
+ it "should not find the application" do
332
377
  app = FactoryBot.create :application
333
- authenticated = Application.by_uid_and_secret(app.uid, app.secret)
334
- expect(authenticated).to eq(app)
335
- end
336
- context "when secret is wrong" do
337
- it "should not find the application" do
338
- app = FactoryBot.create :application
339
- authenticated = Application.by_uid_and_secret(app.uid, "bad")
340
- expect(authenticated).to eq(nil)
341
- end
378
+ authenticated = described_class.by_uid_and_secret(app.uid, "bad")
379
+ expect(authenticated).to eq(nil)
342
380
  end
343
381
  end
382
+ end
344
383
 
345
- context "when application is public/non-confidential" do
346
- context "when secret is blank" do
347
- it "should find the application" do
348
- app = FactoryBot.create :application, confidential: false
349
- authenticated = Application.by_uid_and_secret(app.uid, nil)
350
- expect(authenticated).to eq(app)
351
- end
384
+ context "when application is public/non-confidential" do
385
+ context "when secret is blank" do
386
+ it "should find the application" do
387
+ app = FactoryBot.create :application, confidential: false
388
+ authenticated = described_class.by_uid_and_secret(app.uid, nil)
389
+ expect(authenticated).to eq(app)
352
390
  end
353
- context "when secret is wrong" do
354
- it "should not find the application" do
355
- app = FactoryBot.create :application, confidential: false
356
- authenticated = Application.by_uid_and_secret(app.uid, "bad")
357
- expect(authenticated).to eq(nil)
358
- end
391
+ end
392
+ context "when secret is wrong" do
393
+ it "should not find the application" do
394
+ app = FactoryBot.create :application, confidential: false
395
+ authenticated = described_class.by_uid_and_secret(app.uid, "bad")
396
+ expect(authenticated).to eq(nil)
359
397
  end
360
398
  end
361
399
  end
400
+ end
362
401
 
363
- describe "#confidential?" do
364
- subject { FactoryBot.create(:application, confidential: confidential).confidential? }
402
+ describe "#confidential?" do
403
+ subject { FactoryBot.create(:application, confidential: confidential).confidential? }
365
404
 
366
- context "when application is private/confidential" do
367
- let(:confidential) { true }
368
- it { expect(subject).to eq(true) }
369
- end
405
+ context "when application is private/confidential" do
406
+ let(:confidential) { true }
407
+ it { expect(subject).to eq(true) }
408
+ end
370
409
 
371
- context "when application is public/non-confidential" do
372
- let(:confidential) { false }
373
- it { expect(subject).to eq(false) }
374
- end
410
+ context "when application is public/non-confidential" do
411
+ let(:confidential) { false }
412
+ it { expect(subject).to eq(false) }
375
413
  end
414
+ end
376
415
 
377
- describe "#as_json" do
378
- let(:app) { FactoryBot.create :application, secret: "123123123" }
416
+ describe "#as_json" do
417
+ let(:app) { FactoryBot.create :application, secret: "123123123" }
379
418
 
380
- before do
381
- allow(Doorkeeper.configuration)
382
- .to receive(:application_secret_strategy).and_return(Doorkeeper::SecretStoring::Plain)
383
- end
419
+ before do
420
+ allow(Doorkeeper.configuration)
421
+ .to receive(:application_secret_strategy).and_return(Doorkeeper::SecretStoring::Plain)
422
+ end
384
423
 
385
- it "includes plaintext secret" do
386
- expect(app.as_json).to include("secret" => "123123123")
387
- end
424
+ it "includes plaintext secret" do
425
+ expect(app.as_json).to include("secret" => "123123123")
426
+ end
388
427
 
389
- it "respects custom options" do
390
- expect(app.as_json(except: :secret)).not_to include("secret")
391
- expect(app.as_json(only: :id)).to match("id" => app.id)
392
- end
428
+ it "respects custom options" do
429
+ expect(app.as_json(except: :secret)).not_to include("secret")
430
+ expect(app.as_json(only: :id)).to match("id" => app.id)
431
+ end
393
432
 
394
- # AR specific
395
- if DOORKEEPER_ORM == :active_record
396
- it "correctly works with #to_json" do
397
- ActiveRecord::Base.include_root_in_json = true
398
- expect(app.to_json(include_root_in_json: true)).to match(/application.+?:\{/)
399
- ActiveRecord::Base.include_root_in_json = false
400
- end
433
+ # AR specific
434
+ if DOORKEEPER_ORM == :active_record
435
+ it "correctly works with #to_json" do
436
+ ActiveRecord::Base.include_root_in_json = true
437
+ expect(app.to_json(include_root_in_json: true)).to match(/application.+?:\{/)
438
+ ActiveRecord::Base.include_root_in_json = false
401
439
  end
402
440
  end
403
441
  end