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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
2
4
  def change
3
5
  create_table :oauth_applications do |t|
@@ -167,8 +167,8 @@ module Doorkeeper
167
167
 
168
168
  # We don't know the application secret here (because its hashed) so we can not assert its text on the page
169
169
  # Instead, we read it from the page and then check if it matches the application secret
170
- code_element = %r{<code.*id="secret".*>(.*)<\/code>}.match(response.body)
171
- secret_from_page = code_element[1]
170
+ code_element = /code.*id="secret">\s*\K([^<]*)/m.match(response.body)
171
+ secret_from_page = code_element[1].strip
172
172
 
173
173
  expect(response.body).to have_selector("code#application_id", text: application.uid)
174
174
  expect(response.body).to have_selector("code#secret")
@@ -16,7 +16,14 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
16
16
 
17
17
  let(:client) { FactoryBot.create :application }
18
18
  let(:user) { User.create!(name: "Joe", password: "sekret") }
19
- let(:access_token) { FactoryBot.build :access_token, resource_owner_id: user.id, application_id: client.id, scopes: "default" }
19
+
20
+ let(:access_token) do
21
+ FactoryBot.build :access_token,
22
+ resource_owner_id: user.id,
23
+ resource_owner_type: user.class.name,
24
+ application_id: client.id,
25
+ scopes: "default"
26
+ end
20
27
 
21
28
  before do
22
29
  Doorkeeper.configure do
@@ -136,6 +143,37 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
136
143
  end
137
144
  end
138
145
 
146
+ context "when user cannot access application" do
147
+ before do
148
+ allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
149
+ post :create, params: {
150
+ client_id: client.uid,
151
+ response_type: "token",
152
+ redirect_uri: client.redirect_uri,
153
+ }
154
+ end
155
+
156
+ let(:response_json_body) { JSON.parse(response.body) }
157
+
158
+ it "renders 400 error" do
159
+ expect(response.status).to eq 401
160
+ end
161
+
162
+ it "includes error name" do
163
+ expect(response_json_body["error"]).to eq("invalid_client")
164
+ end
165
+
166
+ it "includes error description" do
167
+ expect(response_json_body["error_description"]).to eq(
168
+ translated_error_message(:invalid_client),
169
+ )
170
+ end
171
+
172
+ it "does not issue any access token" do
173
+ expect(Doorkeeper::AccessToken.all).to be_empty
174
+ end
175
+ end
176
+
139
177
  context "when other error happens" do
140
178
  before do
141
179
  default_scopes_exist :public
@@ -207,6 +245,39 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
207
245
  end
208
246
  end
209
247
 
248
+ context "when user cannot access application" do
249
+ before do
250
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
251
+ allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
252
+
253
+ post :create, params: {
254
+ client_id: client.uid,
255
+ response_type: "token",
256
+ redirect_uri: client.redirect_uri,
257
+ }
258
+ end
259
+
260
+ let(:response_json_body) { JSON.parse(response.body) }
261
+
262
+ it "renders 400 error" do
263
+ expect(response.status).to eq 401
264
+ end
265
+
266
+ it "includes error name" do
267
+ expect(response_json_body["error"]).to eq("invalid_client")
268
+ end
269
+
270
+ it "includes error description" do
271
+ expect(response_json_body["error_description"]).to eq(
272
+ translated_error_message(:invalid_client),
273
+ )
274
+ end
275
+
276
+ it "does not issue any access token" do
277
+ expect(Doorkeeper::AccessToken.all).to be_empty
278
+ end
279
+ end
280
+
210
281
  context "when other error happens" do
211
282
  before do
212
283
  allow(Doorkeeper.config).to receive(:api_only).and_return(true)
@@ -287,12 +358,14 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
287
358
 
288
359
  it "should call :before_successful_authorization callback" do
289
360
  expect(Doorkeeper.config)
290
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
361
+ .to receive_message_chain(:before_successful_authorization, :call)
362
+ .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
291
363
  end
292
364
 
293
365
  it "should call :after_successful_authorization callback" do
294
366
  expect(Doorkeeper.config)
295
- .to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
367
+ .to receive_message_chain(:after_successful_authorization, :call)
368
+ .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
296
369
  end
297
370
  end
298
371
 
@@ -482,46 +555,106 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
482
555
  end
483
556
 
484
557
  describe "GET #new with errors" do
485
- before do
486
- default_scopes_exist :public
487
- get :new, params: { an_invalid: "request" }
488
- end
558
+ context "without valid params" do
559
+ before do
560
+ default_scopes_exist :public
561
+ get :new, params: { an_invalid: "request" }
562
+ end
489
563
 
490
- it "does not redirect" do
491
- expect(response).to_not be_redirect
564
+ it "does not redirect" do
565
+ expect(response).to_not be_redirect
566
+ end
567
+
568
+ it "does not issue any token" do
569
+ expect(Doorkeeper::AccessGrant.count).to eq 0
570
+ expect(Doorkeeper::AccessToken.count).to eq 0
571
+ end
492
572
  end
493
573
 
494
- it "does not issue any token" do
495
- expect(Doorkeeper::AccessGrant.count).to eq 0
496
- expect(Doorkeeper::AccessToken.count).to eq 0
574
+ context "when user cannot access application" do
575
+ before do
576
+ allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
577
+
578
+ get :new, params: {
579
+ client_id: client.uid,
580
+ response_type: "token",
581
+ redirect_uri: client.redirect_uri,
582
+ }
583
+ end
584
+
585
+ it "does not redirect" do
586
+ expect(response).to_not be_redirect
587
+ end
588
+
589
+ it "does not issue any token" do
590
+ expect(Doorkeeper::AccessGrant.count).to eq 0
591
+ expect(Doorkeeper::AccessToken.count).to eq 0
592
+ end
497
593
  end
498
594
  end
499
595
 
500
596
  describe "GET #new in API mode with errors" do
501
- let(:response_json_body) { JSON.parse(response.body) }
502
-
503
597
  before do
504
- default_scopes_exist :public
505
598
  allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
506
- get :new, params: { an_invalid: "request" }
599
+ default_scopes_exist :public
507
600
  end
508
601
 
509
- it "should render bad request" do
510
- expect(response).to have_http_status(:bad_request)
511
- end
602
+ context "without valid params" do
603
+ before do
604
+ get :new, params: { an_invalid: "request" }
605
+ end
512
606
 
513
- it "includes error in body" do
514
- expect(response_json_body["error"]).to eq("invalid_request")
515
- end
607
+ let(:response_json_body) { JSON.parse(response.body) }
608
+
609
+ it "should render bad request" do
610
+ expect(response).to have_http_status(:bad_request)
611
+ end
612
+
613
+ it "includes error in body" do
614
+ expect(response_json_body["error"]).to eq("invalid_request")
615
+ end
516
616
 
517
- it "includes error description in body" do
518
- expect(response_json_body["error_description"])
519
- .to eq(translated_invalid_request_error_message(:missing_param, :client_id))
617
+ it "includes error description in body" do
618
+ expect(response_json_body["error_description"])
619
+ .to eq(translated_invalid_request_error_message(:missing_param, :client_id))
620
+ end
621
+
622
+ it "does not issue any token" do
623
+ expect(Doorkeeper::AccessGrant.count).to eq 0
624
+ expect(Doorkeeper::AccessToken.count).to eq 0
625
+ end
520
626
  end
521
627
 
522
- it "does not issue any token" do
523
- expect(Doorkeeper::AccessGrant.count).to eq 0
524
- expect(Doorkeeper::AccessToken.count).to eq 0
628
+ context "when user cannot access application" do
629
+ before do
630
+ allow(Doorkeeper.configuration).to receive(:authorize_resource_owner_for_client).and_return(->(*_) { false })
631
+
632
+ get :new, params: {
633
+ client_id: client.uid,
634
+ response_type: "token",
635
+ redirect_uri: client.redirect_uri,
636
+ }
637
+ end
638
+
639
+ let(:response_json_body) { JSON.parse(response.body) }
640
+
641
+ it "should render bad request" do
642
+ expect(response).to have_http_status(:bad_request)
643
+ end
644
+
645
+ it "includes error in body" do
646
+ expect(response_json_body["error"]).to eq("invalid_client")
647
+ end
648
+
649
+ it "includes error description in body" do
650
+ expect(response_json_body["error_description"])
651
+ .to eq(translated_error_message(:invalid_client))
652
+ end
653
+
654
+ it "does not issue any token" do
655
+ expect(Doorkeeper::AccessGrant.count).to eq 0
656
+ expect(Doorkeeper::AccessToken.count).to eq 0
657
+ end
525
658
  end
526
659
  end
527
660
 
@@ -538,12 +671,14 @@ describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
538
671
 
539
672
  it "should call :before_successful_authorization callback" do
540
673
  expect(Doorkeeper.configuration)
541
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
674
+ .to receive_message_chain(:before_successful_authorization, :call)
675
+ .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
542
676
  end
543
677
 
544
678
  it "should call :after_successful_authorization callback" do
545
679
  expect(Doorkeeper.configuration)
546
- .to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
680
+ .to receive_message_chain(:after_successful_authorization, :call)
681
+ .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
547
682
  end
548
683
  end
549
684
 
@@ -106,12 +106,13 @@ describe Doorkeeper::TokensController do
106
106
 
107
107
  it "should call :before_successful_authorization callback" do
108
108
  expect(Doorkeeper.configuration)
109
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
109
+ .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
110
110
  end
111
111
 
112
112
  it "should call :after_successful_authorization callback" do
113
113
  expect(Doorkeeper.configuration)
114
- .to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
114
+ .to receive_message_chain(:after_successful_authorization, :call)
115
+ .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
115
116
  end
116
117
  end
117
118
 
@@ -126,7 +127,7 @@ describe Doorkeeper::TokensController do
126
127
 
127
128
  it "should call :before_successful_authorization callback" do
128
129
  expect(Doorkeeper.configuration)
129
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
130
+ .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
130
131
  end
131
132
 
132
133
  it "should not call :after_successful_authorization callback" do
@@ -174,13 +175,13 @@ describe Doorkeeper::TokensController do
174
175
  let(:client) { FactoryBot.create(:application, confidential: false) }
175
176
 
176
177
  it "returns 200" do
177
- post :revoke, params: { token: access_token.token }
178
+ post :revoke, params: { client_id: client.uid, token: access_token.token }
178
179
 
179
180
  expect(response.status).to eq 200
180
181
  end
181
182
 
182
183
  it "revokes the access token" do
183
- post :revoke, params: { token: access_token.token }
184
+ post :revoke, params: { client_id: client.uid, token: access_token.token }
184
185
 
185
186
  expect(access_token.reload).to have_attributes(revoked?: true)
186
187
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ApplicationHelper
4
4
  def current_user
5
- @current_user ||= User.find_by_id(session[:user_id])
5
+ @current_user ||= User.find_by(id: session[:user_id])
6
6
  end
7
7
  end
@@ -1,6 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class User < ActiveRecord::Base
3
+ class ApplicationRecord < ::ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
6
+
7
+ class User < ApplicationRecord
4
8
  def self.authenticate!(name, password)
5
9
  User.where(name: name, password: password).first
6
10
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('boot', __dir__)
1
+ require File.expand_path("boot", __dir__)
2
2
 
3
3
  require "rails"
4
4
 
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  Bundler.require(*Rails.groups)
19
19
 
20
- require 'yaml'
20
+ require "yaml"
21
21
 
22
22
  orm = if DOORKEEPER_ORM =~ /mongoid/
23
23
  Mongoid.load!(File.join(File.dirname(File.expand_path(__FILE__)), "#{DOORKEEPER_ORM}.yml"))
@@ -29,13 +29,15 @@ require "#{orm}/railtie"
29
29
 
30
30
  module Dummy
31
31
  class Application < Rails::Application
32
- if Rails.gem_version < Gem::Version.new('5.1')
32
+ if Rails.gem_version < Gem::Version.new("5.1")
33
33
  config.action_controller.per_form_csrf_tokens = true
34
34
  config.action_controller.forgery_protection_origin_check = true
35
35
 
36
36
  ActiveSupport.to_time_preserves_timezone = true
37
37
 
38
- config.active_record.belongs_to_required_by_default = true
38
+ if DOORKEEPER_ORM =~ /active_record/
39
+ config.active_record.belongs_to_required_by_default = true
40
+ end
39
41
 
40
42
  config.ssl_options = { hsts: { subdomains: true } }
41
43
  else
@@ -1,7 +1,7 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
1
+ require "rubygems"
2
+ require "bundler/setup"
3
3
 
4
- orm = ENV['BUNDLE_GEMFILE'].match(/Gemfile\.(.+)\.rb/)
4
+ orm = ENV["BUNDLE_GEMFILE"].match(/Gemfile\.(.+)\.rb/)
5
5
  DOORKEEPER_ORM = (orm && orm[1]) || :active_record unless defined?(DOORKEEPER_ORM)
6
6
 
7
- $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
7
+ $LOAD_PATH.unshift File.expand_path("../../../lib", __dir__)
@@ -1,5 +1,5 @@
1
1
  # Load the rails application
2
- require File.expand_path('application', __dir__)
2
+ require File.expand_path("application", __dir__)
3
3
 
4
4
  # Initialize the rails application
5
5
  Rails.application.initialize!
@@ -4,10 +4,10 @@ Rails.application.routes.draw do
4
4
  resources :semi_protected_resources
5
5
  resources :full_protected_resources
6
6
 
7
- get 'metal.json' => 'metal#index'
7
+ get "metal.json" => "metal#index"
8
8
 
9
- get '/callback', to: 'home#callback'
10
- get '/sign_in', to: 'home#sign_in'
9
+ get "/callback", to: "home#callback"
10
+ get "/sign_in", to: "home#sign_in"
11
11
 
12
- root to: 'home#index'
12
+ root to: "home#index"
13
13
  end
@@ -18,7 +18,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
18
18
  add_index :oauth_applications, :uid, unique: true
19
19
 
20
20
  create_table :oauth_access_grants do |t|
21
- t.references :resource_owner, null: false
21
+ t.references :resource_owner, null: false, polymorphic: true
22
22
  t.references :application, null: false
23
23
  t.string :token, null: false
24
24
  t.integer :expires_in, null: false
@@ -36,7 +36,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
36
36
  )
37
37
 
38
38
  create_table :oauth_access_tokens do |t|
39
- t.references :resource_owner, index: true
39
+ t.references :resource_owner, index: true, polymorphic: true
40
40
  t.references :application, null: false
41
41
 
42
42
  # If you use a custom token generator you may need to change this column
@@ -14,6 +14,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
14
14
 
15
15
  create_table "oauth_access_grants", force: :cascade do |t|
16
16
  t.integer "resource_owner_id", null: false
17
+ t.string "resource_owner_type" # [NOTE] null: false skipped to allow test pass
17
18
  t.integer "application_id", null: false
18
19
  t.string "token", null: false
19
20
  t.integer "expires_in", null: false
@@ -21,7 +22,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
21
22
  t.datetime "created_at", null: false
22
23
  t.datetime "revoked_at"
23
24
  t.string "scopes"
24
- unless ENV['WITHOUT_PKCE']
25
+ unless ENV["WITHOUT_PKCE"]
25
26
  t.string "code_challenge"
26
27
  t.string "code_challenge_method"
27
28
  end
@@ -30,6 +31,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
30
31
 
31
32
  create_table "oauth_access_tokens", force: :cascade do |t|
32
33
  t.integer "resource_owner_id"
34
+ t.string "resource_owner_type"
33
35
  t.integer "application_id"
34
36
  t.string "token", null: false
35
37
  t.string "refresh_token"
data/spec/factories.rb CHANGED
@@ -26,5 +26,5 @@ FactoryBot.define do
26
26
 
27
27
  # do not name this factory :user, otherwise it will conflict with factories
28
28
  # from applications that use doorkeeper factories in their own tests
29
- factory :doorkeeper_testing_user, class: :user
29
+ factory :doorkeeper_testing_user, class: :user, aliases: [:resource_owner]
30
30
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "generators/doorkeeper/enable_polymorphic_resource_owner_generator"
5
+
6
+ describe "Doorkeeper::EnablePolymorphicResourceOwnerGenerator" do
7
+ include GeneratorSpec::TestCase
8
+
9
+ tests Doorkeeper::EnablePolymorphicResourceOwnerGenerator
10
+ destination ::File.expand_path("../tmp/dummy", __FILE__)
11
+
12
+ describe "after running the generator" do
13
+ before :each do
14
+ prepare_destination
15
+ FileUtils.mkdir_p(::File.expand_path("config/initializers", Pathname(destination_root)))
16
+ FileUtils.copy_file(
17
+ ::File.expand_path("../../lib/generators/doorkeeper/templates/initializer.rb", __dir__),
18
+ ::File.expand_path("config/initializers/doorkeeper.rb", Pathname.new(destination_root)),
19
+ )
20
+ end
21
+
22
+ it "creates a migration with a version specifier and changes the initializer" do
23
+ stub_const("ActiveRecord::VERSION::MAJOR", 5)
24
+ stub_const("ActiveRecord::VERSION::MINOR", 0)
25
+
26
+ run_generator
27
+
28
+ assert_migration "db/migrate/enable_polymorphic_resource_owner.rb" do |migration|
29
+ assert migration.include?("ActiveRecord::Migration[5.0]\n")
30
+ end
31
+
32
+ # generator_spec gem requires such block definition :(
33
+ #
34
+ # rubocop:disable Style/BlockDelimiters
35
+ expect(destination_root).to(have_structure {
36
+ directory "config" do
37
+ directory "initializers" do
38
+ file "doorkeeper.rb" do
39
+ contains " use_polymorphic_resource_owner"
40
+ end
41
+ end
42
+ end
43
+ })
44
+ # rubocop:enable Style/BlockDelimiters
45
+ end
46
+ end
47
+ end
@@ -3,7 +3,7 @@
3
3
  require "spec_helper"
4
4
 
5
5
  describe Doorkeeper, "configuration" do
6
- subject { Doorkeeper.configuration }
6
+ subject { Doorkeeper.config }
7
7
 
8
8
  describe "resource_owner_authenticator" do
9
9
  it "sets the block that is accessible via authenticate_resource_owner" do
@@ -328,7 +328,7 @@ describe Doorkeeper, "configuration" do
328
328
 
329
329
  describe "enable_application_owner" do
330
330
  it "is disabled by default" do
331
- expect(Doorkeeper.configuration.enable_application_owner?).not_to eq(true)
331
+ expect(Doorkeeper.config.enable_application_owner?).not_to eq(true)
332
332
  end
333
333
 
334
334
  context "when enabled without confirmation" do
@@ -344,7 +344,7 @@ describe Doorkeeper, "configuration" do
344
344
  end
345
345
 
346
346
  it "Doorkeeper.configuration.confirm_application_owner? returns false" do
347
- expect(Doorkeeper.configuration.confirm_application_owner?).not_to eq(true)
347
+ expect(Doorkeeper.config.confirm_application_owner?).not_to eq(true)
348
348
  end
349
349
  end
350
350
 
@@ -361,14 +361,14 @@ describe Doorkeeper, "configuration" do
361
361
  end
362
362
 
363
363
  it "Doorkeeper.configuration.confirm_application_owner? returns true" do
364
- expect(Doorkeeper.configuration.confirm_application_owner?).to eq(true)
364
+ expect(Doorkeeper.config.confirm_application_owner?).to eq(true)
365
365
  end
366
366
  end
367
367
  end
368
368
 
369
369
  describe "realm" do
370
370
  it "is 'Doorkeeper' by default" do
371
- expect(Doorkeeper.configuration.realm).to eq("Doorkeeper")
371
+ expect(Doorkeeper.config.realm).to eq("Doorkeeper")
372
372
  end
373
373
 
374
374
  it "can change the value" do
@@ -383,7 +383,7 @@ describe Doorkeeper, "configuration" do
383
383
 
384
384
  describe "grant_flows" do
385
385
  it "is set to all grant flows by default" do
386
- expect(Doorkeeper.configuration.grant_flows)
386
+ expect(Doorkeeper.config.grant_flows)
387
387
  .to eq(%w[authorization_code client_credentials])
388
388
  end
389
389
 
@@ -454,13 +454,13 @@ describe Doorkeeper, "configuration" do
454
454
  end
455
455
 
456
456
  it "raises an exception when configuration is not set" do
457
- old_config = Doorkeeper.configuration
457
+ old_config = Doorkeeper.config
458
458
  Doorkeeper.module_eval do
459
459
  @config = nil
460
460
  end
461
461
 
462
462
  expect do
463
- Doorkeeper.configuration
463
+ Doorkeeper.config
464
464
  end.to raise_error Doorkeeper::MissingConfiguration
465
465
 
466
466
  Doorkeeper.module_eval do
@@ -527,13 +527,13 @@ describe Doorkeeper, "configuration" do
527
527
  end
528
528
  end
529
529
 
530
- it { expect(Doorkeeper.configuration.base_controller).to eq("ApplicationController") }
530
+ it { expect(Doorkeeper.config.base_controller).to eq("ApplicationController") }
531
531
  end
532
532
  end
533
533
 
534
534
  describe "base_metal_controller" do
535
535
  context "default" do
536
- it { expect(Doorkeeper.configuration.base_metal_controller).to eq("ActionController::API") }
536
+ it { expect(Doorkeeper.config.base_metal_controller).to eq("ActionController::API") }
537
537
  end
538
538
 
539
539
  context "custom" do
@@ -565,6 +565,10 @@ describe Doorkeeper, "configuration" do
565
565
  expect(model).to receive(:establish_connection)
566
566
  end
567
567
 
568
+ expect(Kernel).to receive(:warn).with(
569
+ /\[DOORKEEPER\] active_record_options has been deprecated and will soon be removed/,
570
+ )
571
+
568
572
  Doorkeeper.configure do
569
573
  orm DOORKEEPER_ORM
570
574
  active_record_options(
@@ -641,6 +645,21 @@ describe Doorkeeper, "configuration" do
641
645
  end
642
646
  end
643
647
 
648
+ describe "token_lookup_batch_size" do
649
+ it "uses default doorkeeper value" do
650
+ expect(subject.token_lookup_batch_size).to eq(10_000)
651
+ end
652
+
653
+ it "can change the value" do
654
+ Doorkeeper.configure do
655
+ orm DOORKEEPER_ORM
656
+ token_lookup_batch_size 100_000
657
+ end
658
+
659
+ expect(subject.token_lookup_batch_size).to eq(100_000)
660
+ end
661
+ end
662
+
644
663
  describe "strict_content_type" do
645
664
  it "is false by default" do
646
665
  expect(subject.enforce_content_type).to eq(false)
@@ -658,7 +677,7 @@ describe Doorkeeper, "configuration" do
658
677
 
659
678
  describe "handle_auth_errors" do
660
679
  it "is set to render by default" do
661
- expect(Doorkeeper.configuration.handle_auth_errors).to eq(:render)
680
+ expect(Doorkeeper.config.handle_auth_errors).to eq(:render)
662
681
  end
663
682
  it "can change the value" do
664
683
  Doorkeeper.configure do
@@ -13,7 +13,7 @@ describe "Revocable" do
13
13
  it "updates :revoked_at attribute with current time" do
14
14
  utc = double utc: double
15
15
  clock = double now: utc
16
- expect(subject).to receive(:update_attribute).with(:revoked_at, clock.now.utc)
16
+ expect(subject).to receive(:update_column).with(:revoked_at, clock.now.utc)
17
17
  subject.revoke(clock)
18
18
  end
19
19
  end
@@ -36,8 +36,7 @@ describe "Revocable" do
36
36
  end
37
37
 
38
38
  describe :revoke_previous_refresh_token! do
39
- it "revokes the previous token if existing, and resets the
40
- `previous_refresh_token` attribute" do
39
+ it "revokes the previous token if exists and resets the `previous_refresh_token` attribute" do
41
40
  previous_token = FactoryBot.create(
42
41
  :access_token,
43
42
  refresh_token: "refresh_token",
@@ -33,6 +33,14 @@ describe "Doorkeeper::Models::Scopes" do
33
33
  subject.scopes = %w[private admin]
34
34
  expect(subject.scopes_string).to eq("private admin")
35
35
  end
36
+
37
+ it "ignores duplicated scopes" do
38
+ subject.scopes = %w[private admin admin]
39
+ expect(subject.scopes_string).to eq("private admin")
40
+
41
+ subject.scopes = "private admin admin"
42
+ expect(subject.scopes_string).to eq("private admin")
43
+ end
36
44
  end
37
45
 
38
46
  describe :scopes_string do