doorkeeper 5.3.3 → 5.4.0.rc1

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +0 -14
  3. data/CHANGELOG.md +35 -10
  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 +7 -7
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  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.rb +106 -79
  22. data/lib/doorkeeper/config.rb +40 -17
  23. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  24. data/lib/doorkeeper/config/option.rb +28 -14
  25. data/lib/doorkeeper/grape/helpers.rb +1 -1
  26. data/lib/doorkeeper/models/access_grant_mixin.rb +9 -11
  27. data/lib/doorkeeper/models/access_token_mixin.rb +100 -41
  28. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  29. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  30. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  31. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  32. data/lib/doorkeeper/oauth/authorization/code.rb +14 -5
  33. data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
  34. data/lib/doorkeeper/oauth/authorization/token.rb +7 -11
  35. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  36. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
  37. data/lib/doorkeeper/oauth/base_request.rb +11 -19
  38. data/lib/doorkeeper/oauth/client.rb +1 -1
  39. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  40. data/lib/doorkeeper/oauth/client_credentials/creator.rb +25 -7
  41. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  42. data/lib/doorkeeper/oauth/client_credentials/validator.rb +1 -1
  43. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  44. data/lib/doorkeeper/oauth/code_request.rb +1 -1
  45. data/lib/doorkeeper/oauth/code_response.rb +6 -2
  46. data/lib/doorkeeper/oauth/error_response.rb +2 -4
  47. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
  48. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  49. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  50. data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -5
  51. data/lib/doorkeeper/oauth/pre_authorization.rb +32 -27
  52. data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
  53. data/lib/doorkeeper/oauth/token.rb +1 -1
  54. data/lib/doorkeeper/oauth/token_introspection.rb +3 -3
  55. data/lib/doorkeeper/oauth/token_request.rb +2 -2
  56. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  57. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +7 -2
  58. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +6 -2
  59. data/lib/doorkeeper/orm/active_record/mixins/application.rb +9 -64
  60. data/lib/doorkeeper/rails/routes.rb +13 -17
  61. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  62. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  63. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  64. data/lib/doorkeeper/request/strategy.rb +2 -2
  65. data/lib/doorkeeper/server.rb +3 -3
  66. data/lib/doorkeeper/version.rb +3 -3
  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 +39 -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 +15 -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 +22 -62
  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 +16 -5
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Doorkeeper, "configuration option DSL" do
6
+ class Extension
7
+ def self.configure(&block)
8
+ @config = Config::Builder.new(Config.new, &block).build
9
+ end
10
+
11
+ def self.configuration
12
+ @config || (raise Errors::MissingConfiguration)
13
+ end
14
+
15
+ class Config
16
+ class Builder < Doorkeeper::Config::AbstractBuilder
17
+ def enforce_something
18
+ @config.instance_variable_set(:@enforce_something, true)
19
+ end
20
+ end
21
+
22
+ def enforce_something?
23
+ if defined?(@enforce_something)
24
+ @enforce_something
25
+ else
26
+ false
27
+ end
28
+ end
29
+
30
+ def self.builder_class
31
+ Config::Builder
32
+ end
33
+
34
+ extend Doorkeeper::Config::Option
35
+ end
36
+ end
37
+
38
+ it "allows to define custom options in extensions" do
39
+ expect do
40
+ Extension::Config.option(:some_option, default: 1)
41
+ end.not_to raise_error
42
+
43
+ Extension.configure do
44
+ some_option 20
45
+ enforce_something
46
+ end
47
+
48
+ expect(Extension.configuration.some_option).to eq(20)
49
+ expect(Extension.configuration.enforce_something?).to be(true)
50
+ end
51
+ end
@@ -10,6 +10,7 @@ describe Doorkeeper::StaleRecordsCleaner do
10
10
  access_grant: Doorkeeper::AccessGrant,
11
11
  }
12
12
  end
13
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
13
14
 
14
15
  context "when ORM has no cleaner class" do
15
16
  it "raises an error" do
@@ -30,7 +31,10 @@ describe Doorkeeper::StaleRecordsCleaner do
30
31
 
31
32
  context "with revoked record" do
32
33
  before do
33
- FactoryBot.create model_name, revoked_at: Time.current - 1.minute
34
+ FactoryBot.create model_name,
35
+ revoked_at: Time.current - 1.minute,
36
+ resource_owner_id: resource_owner.id,
37
+ resource_owner_type: resource_owner.class.name
34
38
  end
35
39
 
36
40
  it "removes the record" do
@@ -40,7 +44,9 @@ describe Doorkeeper::StaleRecordsCleaner do
40
44
 
41
45
  context "with record revoked in the future" do
42
46
  before do
43
- FactoryBot.create model_name, revoked_at: Time.current + 1.minute
47
+ FactoryBot.create model_name, revoked_at: Time.current + 1.minute,
48
+ resource_owner_id: resource_owner.id,
49
+ resource_owner_type: resource_owner.class.name
44
50
  end
45
51
 
46
52
  it "keeps the record" do
@@ -50,7 +56,9 @@ describe Doorkeeper::StaleRecordsCleaner do
50
56
 
51
57
  context "with unrevoked record" do
52
58
  before do
53
- FactoryBot.create model_name, revoked_at: nil
59
+ FactoryBot.create model_name, revoked_at: nil,
60
+ resource_owner_id: resource_owner.id,
61
+ resource_owner_type: resource_owner.class.name
54
62
  end
55
63
 
56
64
  it "keeps the record" do
@@ -66,7 +74,10 @@ describe Doorkeeper::StaleRecordsCleaner do
66
74
 
67
75
  context "with record that is expired" do
68
76
  before do
69
- FactoryBot.create model_name, created_at: expiry_border - 1.minute
77
+ FactoryBot.create model_name,
78
+ created_at: expiry_border - 1.minute,
79
+ resource_owner_id: resource_owner.id,
80
+ resource_owner_type: resource_owner.class.name
70
81
  end
71
82
 
72
83
  it "removes the record" do
@@ -76,7 +87,9 @@ describe Doorkeeper::StaleRecordsCleaner do
76
87
 
77
88
  context "with record that is not expired" do
78
89
  before do
79
- FactoryBot.create model_name, created_at: expiry_border + 1.minute
90
+ FactoryBot.create model_name, created_at: expiry_border + 1.minute,
91
+ resource_owner_id: resource_owner.id,
92
+ resource_owner_type: resource_owner.class.name
80
93
  end
81
94
 
82
95
  it "keeps the record" do
@@ -3,10 +3,18 @@
3
3
  require "spec_helper"
4
4
 
5
5
  describe Doorkeeper::AccessGrant do
6
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
6
7
  let(:client) { FactoryBot.build_stubbed(:application) }
7
8
  let(:clazz) { Doorkeeper::AccessGrant }
8
9
 
9
- subject { FactoryBot.build(:access_grant, application: client) }
10
+ subject do
11
+ FactoryBot.build(
12
+ :access_grant,
13
+ application: client,
14
+ resource_owner_id: resource_owner.id,
15
+ resource_owner_type: resource_owner.class.name,
16
+ )
17
+ end
10
18
 
11
19
  it { expect(subject).to be_valid }
12
20
 
@@ -17,7 +25,12 @@ describe Doorkeeper::AccessGrant do
17
25
  end
18
26
 
19
27
  context "with hashing enabled" do
20
- let(:grant) { FactoryBot.create :access_grant }
28
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
29
+ let(:grant) do
30
+ FactoryBot.create :access_grant,
31
+ resource_owner_id: resource_owner.id,
32
+ resource_owner_type: resource_owner.class.name
33
+ end
21
34
  include_context "with token hashing enabled"
22
35
 
23
36
  it "holds a volatile plaintext token when created" do
@@ -117,12 +130,12 @@ describe Doorkeeper::AccessGrant do
117
130
  end
118
131
 
119
132
  describe ".revoke_all_for" do
120
- let(:resource_owner) { double(id: 100) }
121
133
  let(:application) { FactoryBot.create :application }
122
134
  let(:default_attributes) do
123
135
  {
124
136
  application: application,
125
137
  resource_owner_id: resource_owner.id,
138
+ resource_owner_type: resource_owner.class.name,
126
139
  }
127
140
  end
128
141
 
@@ -148,9 +161,10 @@ describe Doorkeeper::AccessGrant do
148
161
  end
149
162
 
150
163
  it "matches resource owner" do
164
+ other_resource_owner = FactoryBot.create(:resource_owner)
151
165
  access_grant_for_different_owner = FactoryBot.create(
152
166
  :access_grant,
153
- default_attributes.merge(resource_owner_id: 90),
167
+ default_attributes.merge(resource_owner_id: other_resource_owner.id),
154
168
  )
155
169
 
156
170
  described_class.revoke_all_for application.id, resource_owner
@@ -2,621 +2,649 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- module Doorkeeper
6
- describe AccessToken do
7
- let(:clazz) { Doorkeeper::AccessToken }
8
- subject { FactoryBot.build(:access_token) }
5
+ RSpec.describe Doorkeeper::AccessToken do
6
+ subject { FactoryBot.build(:access_token) }
9
7
 
10
- it { expect(subject).to be_valid }
8
+ it { expect(subject).to be_valid }
11
9
 
12
- it_behaves_like "an accessible token"
13
- it_behaves_like "a revocable token"
14
- it_behaves_like "a unique token" do
15
- let(:factory_name) { :access_token }
16
- end
10
+ it_behaves_like "an accessible token"
11
+ it_behaves_like "a revocable token"
12
+ it_behaves_like "a unique token" do
13
+ let(:factory_name) { :access_token }
14
+ end
15
+
16
+ module CustomGeneratorArgs
17
+ def self.generate; end
18
+ end
19
+
20
+ describe "#generate_token" do
21
+ it "generates a token using the default method" do
22
+ FactoryBot.create :access_token
17
23
 
18
- module CustomGeneratorArgs
19
- def self.generate; end
24
+ token = FactoryBot.create :access_token
25
+ expect(token.token).to be_a(String)
20
26
  end
21
27
 
22
- describe :generate_token do
23
- it "generates a token using the default method" do
24
- FactoryBot.create :access_token
28
+ context "with hashing enabled" do
29
+ let(:token) { FactoryBot.create :access_token }
30
+ include_context "with token hashing enabled"
25
31
 
26
- token = FactoryBot.create :access_token
27
- expect(token.token).to be_a(String)
28
- end
32
+ it "holds a volatile plaintext token when created" do
33
+ expect(token.plaintext_token).to be_a(String)
34
+ expect(token.token)
35
+ .to eq(hashed_or_plain_token_func.call(token.plaintext_token))
29
36
 
30
- context "with hashing enabled" do
31
- let(:token) { FactoryBot.create :access_token }
32
- include_context "with token hashing enabled"
37
+ # Finder method only finds the hashed token
38
+ loaded = described_class.find_by(token: token.token)
39
+ expect(loaded).to eq(token)
40
+ expect(loaded.plaintext_token).to be_nil
41
+ expect(loaded.token).to eq(token.token)
42
+ end
33
43
 
34
- it "holds a volatile plaintext token when created" do
35
- expect(token.plaintext_token).to be_a(String)
36
- expect(token.token)
37
- .to eq(hashed_or_plain_token_func.call(token.plaintext_token))
44
+ it "does not find_by plain text tokens" do
45
+ expect(described_class.find_by(token: token.plaintext_token)).to be_nil
46
+ end
38
47
 
39
- # Finder method only finds the hashed token
40
- loaded = clazz.find_by(token: token.token)
41
- expect(loaded).to eq(token)
42
- expect(loaded.plaintext_token).to be_nil
43
- expect(loaded.token).to eq(token.token)
44
- end
48
+ describe "with having a plain text token" do
49
+ let(:plain_text_token) { "plain text token" }
50
+ let(:access_token) { FactoryBot.create :access_token }
45
51
 
46
- it "does not find_by plain text tokens" do
47
- expect(clazz.find_by(token: token.plaintext_token)).to be_nil
52
+ before do
53
+ # Assume we have a plain text token from before activating the option
54
+ access_token.update_column(:token, plain_text_token)
48
55
  end
49
56
 
50
- describe "with having a plain text token" do
51
- let(:plain_text_token) { "plain text token" }
52
- let(:access_token) { FactoryBot.create :access_token }
57
+ context "without fallback lookup" do
58
+ it "does not provide lookups with either through by_token" do
59
+ expect(described_class.by_token(plain_text_token)).to eq(nil)
60
+ expect(described_class.by_token(access_token.token)).to eq(nil)
53
61
 
54
- before do
55
- # Assume we have a plain text token from before activating the option
56
- access_token.update_column(:token, plain_text_token)
62
+ # And it does not touch the token
63
+ access_token.reload
64
+ expect(access_token.token).to eq(plain_text_token)
57
65
  end
66
+ end
58
67
 
59
- context "without fallback lookup" do
60
- it "does not provide lookups with either through by_token" do
61
- expect(clazz.by_token(plain_text_token)).to eq(nil)
62
- expect(clazz.by_token(access_token.token)).to eq(nil)
63
-
64
- # And it does not touch the token
65
- access_token.reload
66
- expect(access_token.token).to eq(plain_text_token)
68
+ context "with fallback lookup" do
69
+ include_context "with token hashing and fallback lookup enabled"
70
+
71
+ it "upgrades a plain token when falling back to it" do
72
+ # Side-effect: This will automatically upgrade the token
73
+ expect(described_class).to receive(:upgrade_fallback_value).and_call_original
74
+ expect(described_class.by_token(plain_text_token))
75
+ .to have_attributes(
76
+ resource_owner_id: access_token.resource_owner_id,
77
+ application_id: access_token.application_id,
78
+ scopes: access_token.scopes,
79
+ )
80
+
81
+ # Will find subsequently by hashing the token
82
+ expect(described_class.by_token(plain_text_token))
83
+ .to have_attributes(
84
+ resource_owner_id: access_token.resource_owner_id,
85
+ application_id: access_token.application_id,
86
+ scopes: access_token.scopes,
87
+ )
88
+
89
+ # Not all the ORM support :id PK
90
+ if access_token.respond_to?(:id)
91
+ expect(described_class.by_token(plain_text_token).id).to eq(access_token.id)
67
92
  end
68
- end
69
93
 
70
- context "with fallback lookup" do
71
- include_context "with token hashing and fallback lookup enabled"
72
-
73
- it "upgrades a plain token when falling back to it" do
74
- # Side-effect: This will automatically upgrade the token
75
- expect(clazz).to receive(:upgrade_fallback_value).and_call_original
76
- expect(clazz.by_token(plain_text_token))
77
- .to have_attributes(
78
- resource_owner_id: access_token.resource_owner_id,
79
- application_id: access_token.application_id,
80
- scopes: access_token.scopes,
81
- )
82
-
83
- # Will find subsequently by hashing the token
84
- expect(clazz.by_token(plain_text_token))
85
- .to have_attributes(
86
- resource_owner_id: access_token.resource_owner_id,
87
- application_id: access_token.application_id,
88
- scopes: access_token.scopes,
89
- )
90
-
91
- # Not all the ORM support :id PK
92
- if access_token.respond_to?(:id)
93
- expect(clazz.by_token(plain_text_token).id).to eq(access_token.id)
94
- end
95
-
96
- # And it modifies the token value
97
- access_token.reload
98
- expect(access_token.token).not_to eq(plain_text_token)
99
- expect(clazz.find_by(token: plain_text_token)).to eq(nil)
100
- expect(clazz.find_by(token: access_token.token)).not_to be_nil
101
- end
94
+ # And it modifies the token value
95
+ access_token.reload
96
+ expect(access_token.token).not_to eq(plain_text_token)
97
+ expect(described_class.find_by(token: plain_text_token)).to eq(nil)
98
+ expect(described_class.find_by(token: access_token.token)).not_to be_nil
102
99
  end
103
100
  end
104
101
  end
102
+ end
105
103
 
106
- it "generates a token using a custom object" do
107
- eigenclass = class << CustomGeneratorArgs; self; end
108
- eigenclass.class_eval do
109
- remove_method :generate
110
- end
111
- module CustomGeneratorArgs
112
- def self.generate(opts = {})
113
- "custom_generator_token_#{opts[:resource_owner_id]}"
114
- end
115
- end
116
-
117
- Doorkeeper.configure do
118
- orm DOORKEEPER_ORM
119
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
104
+ it "generates a token using a custom object" do
105
+ eigenclass = class << CustomGeneratorArgs; self; end
106
+ eigenclass.class_eval do
107
+ remove_method :generate
108
+ end
109
+ module CustomGeneratorArgs
110
+ def self.generate(opts = {})
111
+ id = opts[:resource_owner_id] || opts[:resource_owner]&.id
112
+ "custom_generator_token_#{id}"
120
113
  end
114
+ end
121
115
 
122
- token = FactoryBot.create :access_token
123
- expect(token.token).to match(/custom_generator_token_\d+/)
116
+ Doorkeeper.configure do
117
+ orm DOORKEEPER_ORM
118
+ access_token_generator "CustomGeneratorArgs"
124
119
  end
125
120
 
126
- it "allows the custom generator to access the application details" do
127
- eigenclass = class << CustomGeneratorArgs; self; end
128
- eigenclass.class_eval do
129
- remove_method :generate
130
- end
121
+ owner = FactoryBot.create :resource_owner
122
+ token = FactoryBot.create :access_token,
123
+ resource_owner_id: owner.id,
124
+ resource_owner_type: owner.class.name
131
125
 
132
- module CustomGeneratorArgs
133
- def self.generate(opts = {})
134
- "custom_generator_token_#{opts[:application].name}"
135
- end
136
- end
126
+ expect(token.token).to match(/custom_generator_token_\d+/)
127
+ end
128
+
129
+ it "allows the custom generator to access the application details" do
130
+ eigenclass = class << CustomGeneratorArgs; self; end
131
+ eigenclass.class_eval do
132
+ remove_method :generate
133
+ end
137
134
 
138
- Doorkeeper.configure do
139
- orm DOORKEEPER_ORM
140
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
135
+ module CustomGeneratorArgs
136
+ def self.generate(opts = {})
137
+ "custom_generator_token_#{opts[:application].name}"
141
138
  end
139
+ end
142
140
 
143
- token = FactoryBot.create :access_token
144
- expect(token.token).to match(/custom_generator_token_Application \d+/)
141
+ Doorkeeper.configure do
142
+ orm DOORKEEPER_ORM
143
+ access_token_generator "CustomGeneratorArgs"
145
144
  end
146
145
 
147
- it "allows the custom generator to access the scopes" do
148
- eigenclass = class << CustomGeneratorArgs; self; end
149
- eigenclass.class_eval do
150
- remove_method :generate
151
- end
152
- module CustomGeneratorArgs
153
- def self.generate(opts = {})
154
- "custom_generator_token_#{opts[:scopes].count}_#{opts[:scopes]}"
155
- end
156
- end
146
+ token = FactoryBot.create :access_token
147
+ expect(token.token).to match(/custom_generator_token_Application \d+/)
148
+ end
157
149
 
158
- Doorkeeper.configure do
159
- orm DOORKEEPER_ORM
160
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
150
+ it "allows the custom generator to access the scopes" do
151
+ eigenclass = class << CustomGeneratorArgs; self; end
152
+ eigenclass.class_eval do
153
+ remove_method :generate
154
+ end
155
+ module CustomGeneratorArgs
156
+ def self.generate(opts = {})
157
+ "custom_generator_token_#{opts[:scopes].count}_#{opts[:scopes]}"
161
158
  end
159
+ end
162
160
 
163
- token = FactoryBot.create :access_token, scopes: "public write"
164
-
165
- expect(token.token).to eq "custom_generator_token_2_public write"
161
+ Doorkeeper.configure do
162
+ orm DOORKEEPER_ORM
163
+ access_token_generator "CustomGeneratorArgs"
166
164
  end
167
165
 
168
- it "allows the custom generator to access the expiry length" do
169
- eigenclass = class << CustomGeneratorArgs; self; end
170
- eigenclass.class_eval do
171
- remove_method :generate
172
- end
173
- module CustomGeneratorArgs
174
- def self.generate(opts = {})
175
- "custom_generator_token_#{opts[:expires_in]}"
176
- end
177
- end
166
+ token = FactoryBot.create :access_token, scopes: "public write"
167
+
168
+ expect(token.token).to eq "custom_generator_token_2_public write"
169
+ end
178
170
 
179
- Doorkeeper.configure do
180
- orm DOORKEEPER_ORM
181
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
171
+ it "allows the custom generator to access the expiry length" do
172
+ eigenclass = class << CustomGeneratorArgs; self; end
173
+ eigenclass.class_eval do
174
+ remove_method :generate
175
+ end
176
+ module CustomGeneratorArgs
177
+ def self.generate(opts = {})
178
+ "custom_generator_token_#{opts[:expires_in]}"
182
179
  end
180
+ end
183
181
 
184
- token = FactoryBot.create :access_token
185
- expect(token.token).to eq "custom_generator_token_7200"
182
+ Doorkeeper.configure do
183
+ orm DOORKEEPER_ORM
184
+ access_token_generator "CustomGeneratorArgs"
186
185
  end
187
186
 
188
- it "allows the custom generator to access the created time" do
189
- module CustomGeneratorArgs
190
- def self.generate(opts = {})
191
- "custom_generator_token_#{opts[:created_at].to_i}"
192
- end
193
- end
187
+ token = FactoryBot.create :access_token
188
+ expect(token.token).to eq "custom_generator_token_7200"
189
+ end
194
190
 
195
- Doorkeeper.configure do
196
- orm DOORKEEPER_ORM
197
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
191
+ it "allows the custom generator to access the created time" do
192
+ module CustomGeneratorArgs
193
+ def self.generate(opts = {})
194
+ "custom_generator_token_#{opts[:created_at].to_i}"
198
195
  end
196
+ end
199
197
 
200
- token = FactoryBot.create :access_token
201
- created_at = token.created_at
202
- expect(token.token).to eq "custom_generator_token_#{created_at.to_i}"
198
+ Doorkeeper.configure do
199
+ orm DOORKEEPER_ORM
200
+ access_token_generator "CustomGeneratorArgs"
203
201
  end
204
202
 
205
- it "raises an error if the custom object does not support generate" do
206
- module NoGenerate
207
- end
203
+ token = FactoryBot.create :access_token
204
+ created_at = token.created_at
205
+ expect(token.token).to eq "custom_generator_token_#{created_at.to_i}"
206
+ end
208
207
 
209
- Doorkeeper.configure do
210
- orm DOORKEEPER_ORM
211
- access_token_generator "Doorkeeper::NoGenerate"
212
- end
208
+ it "raises an error if the custom object does not support generate" do
209
+ module NoGenerate
210
+ end
213
211
 
214
- expect { FactoryBot.create :access_token }.to(
215
- raise_error(Doorkeeper::Errors::UnableToGenerateToken),
216
- )
212
+ Doorkeeper.configure do
213
+ orm DOORKEEPER_ORM
214
+ access_token_generator "NoGenerate"
217
215
  end
218
216
 
219
- it "raises original error if something went wrong in custom generator" do
220
- eigenclass = class << CustomGeneratorArgs; self; end
221
- eigenclass.class_eval do
222
- remove_method :generate
223
- end
217
+ expect { FactoryBot.create :access_token }.to(
218
+ raise_error(Doorkeeper::Errors::UnableToGenerateToken),
219
+ )
220
+ end
224
221
 
225
- module CustomGeneratorArgs
226
- def self.generate(_opts = {})
227
- raise LoadError, "custom behaviour"
228
- end
229
- end
222
+ it "raises original error if something went wrong in custom generator" do
223
+ eigenclass = class << CustomGeneratorArgs; self; end
224
+ eigenclass.class_eval do
225
+ remove_method :generate
226
+ end
230
227
 
231
- Doorkeeper.configure do
232
- orm DOORKEEPER_ORM
233
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
228
+ module CustomGeneratorArgs
229
+ def self.generate(_opts = {})
230
+ raise LoadError, "custom behaviour"
234
231
  end
232
+ end
235
233
 
236
- expect { FactoryBot.create :access_token }.to(
237
- raise_error(LoadError),
238
- )
234
+ Doorkeeper.configure do
235
+ orm DOORKEEPER_ORM
236
+ access_token_generator "CustomGeneratorArgs"
239
237
  end
240
238
 
241
- it "raises an error if the custom object does not exist" do
242
- Doorkeeper.configure do
243
- orm DOORKEEPER_ORM
244
- access_token_generator "Doorkeeper::NotReal"
245
- end
239
+ expect { FactoryBot.create :access_token }.to(
240
+ raise_error(LoadError),
241
+ )
242
+ end
246
243
 
247
- expect { FactoryBot.create :access_token }.to(
248
- raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/),
249
- )
244
+ it "raises an error if the custom object does not exist" do
245
+ Doorkeeper.configure do
246
+ orm DOORKEEPER_ORM
247
+ access_token_generator "Doorkeeper::NotReal"
250
248
  end
249
+
250
+ expect { FactoryBot.create :access_token }.to(
251
+ raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/),
252
+ )
251
253
  end
254
+ end
252
255
 
253
- describe :refresh_token do
254
- it "has empty refresh token if it was not required" do
255
- token = FactoryBot.create :access_token
256
- expect(token.refresh_token).to be_nil
257
- end
256
+ describe "refresh_token" do
257
+ it "has empty refresh token if it was not required" do
258
+ token = FactoryBot.create :access_token
259
+ expect(token.refresh_token).to be_nil
260
+ end
258
261
 
259
- it "generates a refresh token if it was requested" do
260
- token = FactoryBot.create :access_token, use_refresh_token: true
261
- expect(token.refresh_token).not_to be_nil
262
- end
262
+ it "generates a refresh token if it was requested" do
263
+ token = FactoryBot.create :access_token, use_refresh_token: true
264
+ expect(token.refresh_token).not_to be_nil
265
+ end
266
+
267
+ it "is not valid if token exists" do
268
+ token1 = FactoryBot.create :access_token, use_refresh_token: true
269
+ token2 = FactoryBot.create :access_token, use_refresh_token: true
270
+ token2.refresh_token = token1.refresh_token
271
+ expect(token2).not_to be_valid
272
+ end
263
273
 
264
- it "is not valid if token exists" do
265
- token1 = FactoryBot.create :access_token, use_refresh_token: true
266
- token2 = FactoryBot.create :access_token, use_refresh_token: true
274
+ it "expects database to raise an error if refresh tokens are the same" do
275
+ token1 = FactoryBot.create :access_token, use_refresh_token: true
276
+ token2 = FactoryBot.create :access_token, use_refresh_token: true
277
+ expect do
267
278
  token2.refresh_token = token1.refresh_token
268
- expect(token2).not_to be_valid
269
- end
279
+ token2.save(validate: false)
280
+ end.to raise_error(uniqueness_error)
281
+ end
270
282
 
271
- it "expects database to raise an error if refresh tokens are the same" do
272
- token1 = FactoryBot.create :access_token, use_refresh_token: true
273
- token2 = FactoryBot.create :access_token, use_refresh_token: true
274
- expect do
275
- token2.refresh_token = token1.refresh_token
276
- token2.save(validate: false)
277
- end.to raise_error(uniqueness_error)
278
- end
283
+ context "with hashing enabled" do
284
+ include_context "with token hashing enabled"
285
+ let(:token) { FactoryBot.create :access_token, use_refresh_token: true }
279
286
 
280
- context "with hashing enabled" do
281
- include_context "with token hashing enabled"
282
- let(:token) { FactoryBot.create :access_token, use_refresh_token: true }
287
+ it "holds a volatile refresh token when created" do
288
+ expect(token.plaintext_refresh_token).to be_a(String)
289
+ expect(token.refresh_token)
290
+ .to eq(hashed_or_plain_token_func.call(token.plaintext_refresh_token))
283
291
 
284
- it "holds a volatile refresh token when created" do
285
- expect(token.plaintext_refresh_token).to be_a(String)
286
- expect(token.refresh_token)
287
- .to eq(hashed_or_plain_token_func.call(token.plaintext_refresh_token))
292
+ # Finder method only finds the hashed token
293
+ loaded = described_class.find_by(refresh_token: token.refresh_token)
294
+ expect(loaded).to eq(token)
295
+ expect(loaded.plaintext_refresh_token).to be_nil
296
+ expect(loaded.refresh_token).to eq(token.refresh_token)
297
+ end
288
298
 
289
- # Finder method only finds the hashed token
290
- loaded = clazz.find_by(refresh_token: token.refresh_token)
291
- expect(loaded).to eq(token)
292
- expect(loaded.plaintext_refresh_token).to be_nil
293
- expect(loaded.refresh_token).to eq(token.refresh_token)
294
- end
299
+ it "does not find_by plain text refresh tokens" do
300
+ expect(described_class.find_by(refresh_token: token.plaintext_refresh_token)).to be_nil
301
+ end
302
+
303
+ describe "with having a plain text token" do
304
+ let(:plain_refresh_token) { "plain refresh token" }
305
+ let(:access_token) { FactoryBot.create :access_token }
295
306
 
296
- it "does not find_by plain text refresh tokens" do
297
- expect(clazz.find_by(refresh_token: token.plaintext_refresh_token)).to be_nil
307
+ before do
308
+ # Assume we have a plain text token from before activating the option
309
+ access_token.update_column(:refresh_token, plain_refresh_token)
298
310
  end
299
311
 
300
- describe "with having a plain text token" do
301
- let(:plain_refresh_token) { "plain refresh token" }
302
- let(:access_token) { FactoryBot.create :access_token }
312
+ context "without fallback lookup" do
313
+ it "does not provide lookups with either through by_token" do
314
+ expect(described_class.by_refresh_token(plain_refresh_token)).to eq(nil)
315
+ expect(described_class.by_refresh_token(access_token.refresh_token)).to eq(nil)
303
316
 
304
- before do
305
- # Assume we have a plain text token from before activating the option
306
- access_token.update_column(:refresh_token, plain_refresh_token)
317
+ # And it does not touch the token
318
+ access_token.reload
319
+ expect(access_token.refresh_token).to eq(plain_refresh_token)
307
320
  end
321
+ end
308
322
 
309
- context "without fallback lookup" do
310
- it "does not provide lookups with either through by_token" do
311
- expect(clazz.by_refresh_token(plain_refresh_token)).to eq(nil)
312
- expect(clazz.by_refresh_token(access_token.refresh_token)).to eq(nil)
313
-
314
- # And it does not touch the token
315
- access_token.reload
316
- expect(access_token.refresh_token).to eq(plain_refresh_token)
323
+ context "with fallback lookup" do
324
+ include_context "with token hashing and fallback lookup enabled"
325
+
326
+ it "upgrades a plain token when falling back to it" do
327
+ # Side-effect: This will automatically upgrade the token
328
+ expect(described_class).to receive(:upgrade_fallback_value).and_call_original
329
+ expect(described_class.by_refresh_token(plain_refresh_token))
330
+ .to have_attributes(
331
+ token: access_token.token,
332
+ resource_owner_id: access_token.resource_owner_id,
333
+ application_id: access_token.application_id,
334
+ )
335
+
336
+ # Will find subsequently by hashing the token
337
+ expect(described_class.by_refresh_token(plain_refresh_token))
338
+ .to have_attributes(
339
+ token: access_token.token,
340
+ resource_owner_id: access_token.resource_owner_id,
341
+ application_id: access_token.application_id,
342
+ )
343
+
344
+ # Not all the ORM support :id PK
345
+ if access_token.respond_to?(:id)
346
+ expect(described_class.by_refresh_token(plain_refresh_token).id).to eq(access_token.id)
317
347
  end
318
- end
319
348
 
320
- context "with fallback lookup" do
321
- include_context "with token hashing and fallback lookup enabled"
322
-
323
- it "upgrades a plain token when falling back to it" do
324
- # Side-effect: This will automatically upgrade the token
325
- expect(clazz).to receive(:upgrade_fallback_value).and_call_original
326
- expect(clazz.by_refresh_token(plain_refresh_token))
327
- .to have_attributes(
328
- token: access_token.token,
329
- resource_owner_id: access_token.resource_owner_id,
330
- application_id: access_token.application_id,
331
- )
332
-
333
- # Will find subsequently by hashing the token
334
- expect(clazz.by_refresh_token(plain_refresh_token))
335
- .to have_attributes(
336
- token: access_token.token,
337
- resource_owner_id: access_token.resource_owner_id,
338
- application_id: access_token.application_id,
339
- )
340
-
341
- # Not all the ORM support :id PK
342
- if access_token.respond_to?(:id)
343
- expect(clazz.by_refresh_token(plain_refresh_token).id).to eq(access_token.id)
344
- end
345
-
346
- # And it modifies the token value
347
- access_token.reload
348
- expect(access_token.refresh_token).not_to eq(plain_refresh_token)
349
- expect(clazz.find_by(refresh_token: plain_refresh_token)).to eq(nil)
350
- expect(clazz.find_by(refresh_token: access_token.refresh_token)).not_to be_nil
351
- end
349
+ # And it modifies the token value
350
+ access_token.reload
351
+ expect(access_token.refresh_token).not_to eq(plain_refresh_token)
352
+ expect(described_class.find_by(refresh_token: plain_refresh_token)).to eq(nil)
353
+ expect(described_class.find_by(refresh_token: access_token.refresh_token)).not_to be_nil
352
354
  end
353
355
  end
354
356
  end
355
357
  end
358
+ end
356
359
 
357
- describe "validations" do
358
- it "is valid without resource_owner_id" do
359
- # For client credentials flow
360
- subject.resource_owner_id = nil
361
- expect(subject).to be_valid
362
- end
360
+ describe "validations" do
361
+ it "is valid without resource_owner_id" do
362
+ # For client credentials flow
363
+ subject.resource_owner_id = nil
364
+ expect(subject).to be_valid
365
+ end
363
366
 
364
- it "is valid without application_id" do
365
- # For resource owner credentials flow
366
- subject.application_id = nil
367
- expect(subject).to be_valid
368
- end
367
+ it "is valid without application_id" do
368
+ # For resource owner credentials flow
369
+ subject.application_id = nil
370
+ expect(subject).to be_valid
369
371
  end
372
+ end
370
373
 
371
- describe "#same_credential?" do
372
- context "with default parameters" do
373
- let(:resource_owner_id) { 100 }
374
- let(:application) { FactoryBot.create :application }
375
- let(:default_attributes) do
376
- { application: application, resource_owner_id: resource_owner_id }
377
- end
378
- let(:access_token1) { FactoryBot.create :access_token, default_attributes }
374
+ describe "#same_credential?" do
375
+ context "with default parameters" do
376
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
377
+ let(:resource_owner_id) { resource_owner.id }
378
+ let(:application) { FactoryBot.create :application }
379
+ let(:default_attributes) do
380
+ {
381
+ application: application,
382
+ resource_owner_id: resource_owner_id,
383
+ resource_owner_type: resource_owner.class.name,
384
+ }
385
+ end
386
+ let(:access_token1) { FactoryBot.create :access_token, default_attributes }
379
387
 
380
- context "the second token has the same owner and same app" do
381
- let(:access_token2) { FactoryBot.create :access_token, default_attributes }
382
- it "success" do
383
- expect(access_token1.same_credential?(access_token2)).to be_truthy
384
- end
388
+ context "the second token has the same owner and same app" do
389
+ let(:access_token2) { FactoryBot.create :access_token, default_attributes }
390
+ it "success" do
391
+ expect(access_token1.same_credential?(access_token2)).to be_truthy
385
392
  end
393
+ end
386
394
 
387
- context "the second token has same owner and different app" do
388
- let(:other_application) { FactoryBot.create :application }
389
- let(:access_token2) do
390
- FactoryBot.create :access_token,
391
- application: other_application,
392
- resource_owner_id: resource_owner_id
393
- end
395
+ context "the second token has same owner and different app" do
396
+ let(:other_application) { FactoryBot.create :application }
397
+ let(:access_token2) do
398
+ FactoryBot.create :access_token,
399
+ application: other_application,
400
+ resource_owner_id: resource_owner_id,
401
+ resource_owner_type: resource_owner.class.name
402
+ end
394
403
 
395
- it "fail" do
396
- expect(access_token1.same_credential?(access_token2)).to be_falsey
397
- end
404
+ it "fail" do
405
+ expect(access_token1.same_credential?(access_token2)).to be_falsey
398
406
  end
407
+ end
399
408
 
400
- context "the second token has different owner and different app" do
401
- let(:other_application) { FactoryBot.create :application }
402
- let(:access_token2) do
403
- FactoryBot.create :access_token, application: other_application, resource_owner_id: 42
404
- end
409
+ context "the second token has different owner and different app" do
410
+ let(:other_application) { FactoryBot.create :application }
411
+ let(:access_token2) do
412
+ FactoryBot.create :access_token,
413
+ application: other_application,
414
+ resource_owner_id: resource_owner.id + 1
415
+ end
405
416
 
406
- it "fail" do
407
- expect(access_token1.same_credential?(access_token2)).to be_falsey
408
- end
417
+ it "fail" do
418
+ expect(access_token1.same_credential?(access_token2)).to be_falsey
409
419
  end
420
+ end
410
421
 
411
- context "the second token has different owner and same app" do
412
- let(:access_token2) do
413
- FactoryBot.create :access_token, application: application, resource_owner_id: 42
414
- end
422
+ context "the second token has different owner and same app" do
423
+ let(:access_token2) do
424
+ FactoryBot.create :access_token,
425
+ application: application,
426
+ resource_owner_id: resource_owner.id + 1
427
+ end
415
428
 
416
- it "fail" do
417
- expect(access_token1.same_credential?(access_token2)).to be_falsey
418
- end
429
+ it "fail" do
430
+ expect(access_token1.same_credential?(access_token2)).to be_falsey
419
431
  end
420
432
  end
421
433
  end
434
+ end
422
435
 
423
- describe "#acceptable?" do
424
- context "a token that is not accessible" do
425
- let(:token) { FactoryBot.create(:access_token, created_at: 6.hours.ago) }
436
+ describe "#acceptable?" do
437
+ context "a token that is not accessible" do
438
+ let(:token) { FactoryBot.create(:access_token, created_at: 6.hours.ago) }
426
439
 
427
- it "should return false" do
428
- expect(token.acceptable?(nil)).to be false
429
- end
440
+ it "should return false" do
441
+ expect(token.acceptable?(nil)).to be false
430
442
  end
443
+ end
431
444
 
432
- context "a token that has the incorrect scopes" do
433
- let(:token) { FactoryBot.create(:access_token) }
445
+ context "a token that has the incorrect scopes" do
446
+ let(:token) { FactoryBot.create(:access_token) }
434
447
 
435
- it "should return false" do
436
- expect(token.acceptable?(["public"])).to be false
437
- end
448
+ it "should return false" do
449
+ expect(token.acceptable?(["public"])).to be false
438
450
  end
451
+ end
439
452
 
440
- context "a token is acceptable with the correct scopes" do
441
- let(:token) do
442
- token = FactoryBot.create(:access_token)
443
- token[:scopes] = "public"
444
- token
445
- end
453
+ context "a token is acceptable with the correct scopes" do
454
+ let(:token) do
455
+ token = FactoryBot.create(:access_token)
456
+ token[:scopes] = "public"
457
+ token
458
+ end
446
459
 
447
- it "should return true" do
448
- expect(token.acceptable?(["public"])).to be true
449
- end
460
+ it "should return true" do
461
+ expect(token.acceptable?(["public"])).to be true
450
462
  end
451
463
  end
464
+ end
452
465
 
453
- describe ".revoke_all_for" do
454
- let(:resource_owner) { double(id: 100) }
455
- let(:application) { FactoryBot.create :application }
456
- let(:default_attributes) do
457
- { application: application, resource_owner_id: resource_owner.id }
458
- end
466
+ describe ".revoke_all_for" do
467
+ let(:resource_owner) { FactoryBot.create :resource_owner }
468
+ let(:application) { FactoryBot.create :application }
469
+ let(:default_attributes) do
470
+ {
471
+ application: application,
472
+ resource_owner_id: resource_owner.id,
473
+ resource_owner_type: resource_owner.class.name,
474
+ }
475
+ end
459
476
 
460
- it "revokes all tokens for given application and resource owner" do
461
- FactoryBot.create :access_token, default_attributes
462
- AccessToken.revoke_all_for application.id, resource_owner
463
- AccessToken.all.each do |token|
464
- expect(token).to be_revoked
465
- end
477
+ it "revokes all tokens for given application and resource owner" do
478
+ FactoryBot.create :access_token, default_attributes
479
+ described_class.revoke_all_for application.id, resource_owner
480
+ described_class.all.each do |token|
481
+ expect(token).to be_revoked
466
482
  end
483
+ end
467
484
 
468
- it "matches application" do
469
- access_token_for_different_app = FactoryBot.create(
470
- :access_token,
471
- default_attributes.merge(application: FactoryBot.create(:application)),
472
- )
485
+ it "matches application" do
486
+ access_token_for_different_app = FactoryBot.create(
487
+ :access_token,
488
+ default_attributes.merge(application: FactoryBot.create(:application)),
489
+ )
473
490
 
474
- AccessToken.revoke_all_for application.id, resource_owner
491
+ described_class.revoke_all_for application.id, resource_owner
475
492
 
476
- expect(access_token_for_different_app.reload).not_to be_revoked
477
- end
493
+ expect(access_token_for_different_app.reload).not_to be_revoked
494
+ end
478
495
 
479
- it "matches resource owner" do
480
- access_token_for_different_owner = FactoryBot.create(
481
- :access_token,
482
- default_attributes.merge(resource_owner_id: 90),
483
- )
496
+ it "matches resource owner" do
497
+ access_token_for_different_owner = FactoryBot.create(
498
+ :access_token,
499
+ default_attributes.merge(resource_owner_id: resource_owner.id + 1),
500
+ )
484
501
 
485
- AccessToken.revoke_all_for application.id, resource_owner
502
+ described_class.revoke_all_for application.id, resource_owner
486
503
 
487
- expect(access_token_for_different_owner.reload).not_to be_revoked
488
- end
504
+ expect(access_token_for_different_owner.reload).not_to be_revoked
489
505
  end
506
+ end
490
507
 
491
- describe ".matching_token_for" do
492
- let(:resource_owner_id) { 100 }
493
- let(:application) { FactoryBot.create :application }
494
- let(:scopes) { Doorkeeper::OAuth::Scopes.from_string("public write") }
495
- let(:default_attributes) do
496
- {
497
- application: application,
498
- resource_owner_id: resource_owner_id,
499
- scopes: scopes.to_s,
500
- }
501
- end
508
+ describe ".matching_token_for" do
509
+ let(:resource_owner) { FactoryBot.create :resource_owner }
510
+ let(:resource_owner_id) { resource_owner.id }
511
+ let(:application) { FactoryBot.create :application }
512
+ let(:scopes) { Doorkeeper::OAuth::Scopes.from_string("public write") }
513
+ let(:default_attributes) do
514
+ {
515
+ application: application,
516
+ resource_owner_id: resource_owner_id,
517
+ resource_owner_type: resource_owner.class.name,
518
+ scopes: scopes.to_s,
519
+ }
520
+ end
502
521
 
503
- before do
504
- default_scopes_exist(*scopes.all)
505
- end
522
+ before do
523
+ default_scopes_exist(*scopes.all)
524
+ end
506
525
 
507
- it "returns only one token" do
508
- token = FactoryBot.create :access_token, default_attributes
509
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
510
- expect(last_token).to eq(token)
511
- end
526
+ it "returns only one token" do
527
+ token = FactoryBot.create :access_token, default_attributes
528
+ last_token = described_class.matching_token_for(application, resource_owner, scopes)
529
+ expect(last_token).to eq(token)
530
+ end
512
531
 
513
- it "accepts resource owner as object" do
514
- resource_owner = double(to_key: true, id: 100)
515
- token = FactoryBot.create :access_token, default_attributes
516
- last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
517
- expect(last_token).to eq(token)
518
- end
532
+ it "accepts resource owner as object" do
533
+ token = FactoryBot.create :access_token, default_attributes
534
+ last_token = described_class.matching_token_for(application, resource_owner, scopes)
535
+ expect(last_token).to eq(token)
536
+ end
519
537
 
520
- it "accepts nil as resource owner" do
521
- token = FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: nil)
522
- last_token = AccessToken.matching_token_for(application, nil, scopes)
523
- expect(last_token).to eq(token)
524
- end
538
+ it "accepts nil as resource owner" do
539
+ token = FactoryBot.create :access_token,
540
+ default_attributes.merge(resource_owner_id: nil, resource_owner_type: nil)
541
+ last_token = described_class.matching_token_for(application, nil, scopes)
542
+ expect(last_token).to eq(token)
543
+ end
525
544
 
526
- it "excludes revoked tokens" do
527
- FactoryBot.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
528
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
529
- expect(last_token).to be_nil
530
- end
545
+ it "excludes revoked tokens" do
546
+ FactoryBot.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
547
+ last_token = described_class.matching_token_for(application, resource_owner_id, scopes)
548
+ expect(last_token).to be_nil
549
+ end
531
550
 
532
- it "excludes tokens with a different application" do
533
- FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
534
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
535
- expect(last_token).to be_nil
536
- end
551
+ it "excludes tokens with a different application" do
552
+ FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
553
+ last_token = described_class.matching_token_for(application, resource_owner_id, scopes)
554
+ expect(last_token).to be_nil
555
+ end
537
556
 
538
- it "excludes tokens with a different resource owner" do
539
- FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
540
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
541
- expect(last_token).to be_nil
542
- end
557
+ it "excludes tokens with a different resource owner" do
558
+ FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: resource_owner.id + 1)
559
+ last_token = described_class.matching_token_for(application, resource_owner_id, scopes)
560
+ expect(last_token).to be_nil
561
+ end
543
562
 
544
- it "excludes tokens with fewer scopes" do
545
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public")
546
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
547
- expect(last_token).to be_nil
548
- end
563
+ it "excludes tokens with fewer scopes" do
564
+ FactoryBot.create :access_token, default_attributes.merge(scopes: "public")
565
+ last_token = described_class.matching_token_for(application, resource_owner_id, scopes)
566
+ expect(last_token).to be_nil
567
+ end
549
568
 
550
- it "excludes tokens with different scopes" do
551
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public email")
552
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
553
- expect(last_token).to be_nil
554
- end
569
+ it "excludes tokens with different scopes" do
570
+ FactoryBot.create :access_token, default_attributes.merge(scopes: "public email")
571
+ last_token = described_class.matching_token_for(application, resource_owner, scopes)
572
+ expect(last_token).to be_nil
573
+ end
555
574
 
556
- it "excludes tokens with additional scopes" do
557
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public write email")
558
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
559
- expect(last_token).to be_nil
560
- end
575
+ it "excludes tokens with additional scopes" do
576
+ FactoryBot.create :access_token, default_attributes.merge(scopes: "public write email")
577
+ last_token = described_class.matching_token_for(application, resource_owner, scopes)
578
+ expect(last_token).to be_nil
579
+ end
561
580
 
562
- it "excludes tokens with scopes that are not present in server scopes" do
563
- FactoryBot.create :access_token, default_attributes.merge(
564
- application: application, scopes: "public read",
565
- )
566
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
567
- expect(last_token).to be_nil
568
- end
581
+ it "excludes tokens with scopes that are not present in server scopes" do
582
+ FactoryBot.create :access_token, default_attributes.merge(
583
+ application: application, scopes: "public read",
584
+ )
585
+ last_token = described_class.matching_token_for(application, resource_owner, scopes)
586
+ expect(last_token).to be_nil
587
+ end
569
588
 
570
- it "excludes tokens with scopes that are not present in application scopes" do
571
- application = FactoryBot.create :application, scopes: "private read"
572
- FactoryBot.create :access_token, default_attributes.merge(
573
- application: application,
574
- )
575
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
576
- expect(last_token).to be_nil
577
- end
589
+ it "excludes tokens with scopes that are not present in application scopes" do
590
+ application = FactoryBot.create :application, scopes: "private read"
591
+ FactoryBot.create :access_token, default_attributes.merge(
592
+ application: application,
593
+ )
594
+ last_token = described_class.matching_token_for(application, resource_owner, scopes)
595
+ expect(last_token).to be_nil
596
+ end
578
597
 
579
- it "does not match token if empty scope requested and token/app scopes present" do
580
- application = FactoryBot.create :application, scopes: "sample:scope"
581
- app_params = {
582
- application_id: application.id, scopes: "sample:scope",
583
- resource_owner_id: 100,
584
- }
585
- FactoryBot.create :access_token, app_params
586
- empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
587
- last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
588
- expect(last_token).to be_nil
589
- end
598
+ it "does not match token if empty scope requested and token/app scopes present" do
599
+ application = FactoryBot.create :application, scopes: "sample:scope"
600
+ app_params = {
601
+ application_id: application.id, scopes: "sample:scope",
602
+ resource_owner_id: resource_owner.id,
603
+ resource_owner_type: resource_owner.class.name,
604
+ }
605
+ FactoryBot.create :access_token, app_params
606
+ empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
607
+ last_token = described_class.matching_token_for(application, resource_owner.id, empty_scopes)
608
+ expect(last_token).to be_nil
609
+ end
590
610
 
591
- it "matches token if empty scope requested and no token scopes present" do
592
- empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
593
- token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
594
- last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
595
- expect(last_token).to eq(token)
596
- end
611
+ it "matches token if empty scope requested and no token scopes present" do
612
+ empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
613
+ token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
614
+ last_token = described_class.matching_token_for(application, resource_owner.id, empty_scopes)
615
+ expect(last_token).to eq(token)
616
+ end
597
617
 
598
- it "returns the last matching token" do
599
- FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
600
- matching_token = FactoryBot.create :access_token, default_attributes
601
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public")
618
+ it "returns the last matching token" do
619
+ FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
620
+ matching_token = FactoryBot.create :access_token, default_attributes
621
+ FactoryBot.create :access_token, default_attributes.merge(scopes: "public")
602
622
 
603
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
604
- expect(last_token).to eq(matching_token)
605
- end
623
+ last_token = described_class.matching_token_for(application, resource_owner_id, scopes)
624
+ expect(last_token).to eq(matching_token)
625
+ end
626
+ end
627
+
628
+ describe "#as_json" do
629
+ let(:token) { FactoryBot.create(:access_token) }
630
+ let(:token_hash) do
631
+ {
632
+ resource_owner_id: token.resource_owner_id,
633
+ scope: token.scopes,
634
+ expires_in: token.expires_in_seconds,
635
+ application: { uid: token.application.uid },
636
+ created_at: token.created_at.to_i,
637
+ }
606
638
  end
607
639
 
608
- describe "#as_json" do
609
- it "returns as_json hash" do
610
- token = FactoryBot.create :access_token
611
- token_hash = {
612
- resource_owner_id: token.resource_owner_id,
613
- scope: token.scopes,
614
- expires_in: token.expires_in_seconds,
615
- application: { uid: token.application.uid },
616
- created_at: token.created_at.to_i,
617
- }
618
- expect(token.as_json).to eq token_hash
640
+ it "returns as_json hash" do
641
+ hash = token_hash
642
+
643
+ if Doorkeeper.configuration.polymorphic_resource_owner?
644
+ hash[:resource_owner_type] = token.resource_owner_type
619
645
  end
646
+
647
+ expect(token.as_json).to match(hash)
620
648
  end
621
649
  end
622
650
  end