doorkeeper 5.0.3 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +2 -1
  3. data/.rubocop.yml +37 -4
  4. data/.travis.yml +11 -21
  5. data/Appraisals +29 -7
  6. data/Dangerfile +5 -2
  7. data/Gemfile +19 -5
  8. data/NEWS.md +81 -21
  9. data/README.md +75 -485
  10. data/Rakefile +10 -8
  11. data/app/controllers/doorkeeper/application_controller.rb +1 -2
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -13
  13. data/app/controllers/doorkeeper/applications_controller.rb +20 -8
  14. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  15. data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
  16. data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
  17. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  18. data/app/validators/redirect_uri_validator.rb +5 -2
  19. data/app/views/doorkeeper/applications/_form.html.erb +6 -0
  20. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  21. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  22. data/bin/console +16 -0
  23. data/config/locales/en.yml +1 -0
  24. data/doorkeeper.gemspec +24 -21
  25. data/gemfiles/rails_5_0.gemfile +9 -4
  26. data/gemfiles/rails_5_1.gemfile +9 -4
  27. data/gemfiles/rails_5_2.gemfile +10 -5
  28. data/gemfiles/rails_6_0.gemfile +17 -0
  29. data/gemfiles/rails_master.gemfile +9 -9
  30. data/lib/doorkeeper/config/option.rb +64 -0
  31. data/lib/doorkeeper/config.rb +191 -75
  32. data/lib/doorkeeper/engine.rb +1 -1
  33. data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
  34. data/lib/doorkeeper/grape/helpers.rb +3 -3
  35. data/lib/doorkeeper/helpers/controller.rb +3 -2
  36. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
  37. data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
  38. data/lib/doorkeeper/models/application_mixin.rb +43 -1
  39. data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
  40. data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
  41. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  42. data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
  43. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  44. data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
  45. data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
  46. data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
  47. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  48. data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
  49. data/lib/doorkeeper/oauth/client.rb +1 -1
  50. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -4
  51. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  52. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  53. data/lib/doorkeeper/oauth/error_response.rb +10 -6
  54. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  55. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
  56. data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
  57. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
  58. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
  59. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  60. data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
  61. data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
  62. data/lib/doorkeeper/oauth/scopes.rb +5 -3
  63. data/lib/doorkeeper/oauth/token.rb +2 -2
  64. data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
  65. data/lib/doorkeeper/oauth/token_response.rb +9 -9
  66. data/lib/doorkeeper/oauth.rb +5 -5
  67. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
  68. data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
  69. data/lib/doorkeeper/orm/active_record/application.rb +21 -57
  70. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
  71. data/lib/doorkeeper/orm/active_record.rb +6 -6
  72. data/lib/doorkeeper/rails/helpers.rb +1 -1
  73. data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
  74. data/lib/doorkeeper/rails/routes.rb +11 -11
  75. data/lib/doorkeeper/rake/db.rake +13 -13
  76. data/lib/doorkeeper/rake.rb +1 -1
  77. data/lib/doorkeeper/request.rb +1 -1
  78. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  79. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  80. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  81. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  82. data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
  83. data/lib/doorkeeper/version.rb +3 -3
  84. data/lib/doorkeeper.rb +69 -60
  85. data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
  86. data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
  87. data/lib/generators/doorkeeper/install_generator.rb +11 -9
  88. data/lib/generators/doorkeeper/migration_generator.rb +9 -9
  89. data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
  90. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
  91. data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
  92. data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
  93. data/lib/generators/doorkeeper/views_generator.rb +6 -4
  94. data/spec/controllers/application_metal_controller_spec.rb +24 -10
  95. data/spec/controllers/applications_controller_spec.rb +54 -52
  96. data/spec/controllers/authorizations_controller_spec.rb +139 -145
  97. data/spec/controllers/protected_resources_controller_spec.rb +78 -76
  98. data/spec/controllers/token_info_controller_spec.rb +14 -12
  99. data/spec/controllers/tokens_controller_spec.rb +167 -108
  100. data/spec/dummy/Rakefile +3 -1
  101. data/spec/dummy/app/controllers/application_controller.rb +3 -1
  102. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
  103. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
  104. data/spec/dummy/app/controllers/home_controller.rb +5 -3
  105. data/spec/dummy/app/controllers/metal_controller.rb +2 -0
  106. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
  107. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  108. data/spec/dummy/app/models/user.rb +2 -0
  109. data/spec/dummy/config/application.rb +25 -1
  110. data/spec/dummy/config/environments/development.rb +2 -0
  111. data/spec/dummy/config/environments/production.rb +2 -0
  112. data/spec/dummy/config/environments/test.rb +3 -1
  113. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  114. data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
  115. data/spec/dummy/config/initializers/secret_token.rb +3 -1
  116. data/spec/dummy/config/initializers/session_store.rb +3 -1
  117. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  118. data/spec/dummy/config.ru +3 -1
  119. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
  120. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
  121. data/spec/dummy/db/schema.rb +1 -1
  122. data/spec/dummy/script/rails +5 -3
  123. data/spec/factories.rb +8 -6
  124. data/spec/generators/application_owner_generator_spec.rb +13 -26
  125. data/spec/generators/confidential_applications_generator_spec.rb +12 -28
  126. data/spec/generators/install_generator_spec.rb +17 -15
  127. data/spec/generators/migration_generator_spec.rb +13 -26
  128. data/spec/generators/pkce_generator_spec.rb +11 -26
  129. data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
  130. data/spec/generators/templates/routes.rb +2 -0
  131. data/spec/generators/views_generator_spec.rb +14 -12
  132. data/spec/grape/grape_integration_spec.rb +34 -32
  133. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
  134. data/spec/lib/config_spec.rb +268 -99
  135. data/spec/lib/doorkeeper_spec.rb +3 -1
  136. data/spec/lib/models/expirable_spec.rb +22 -8
  137. data/spec/lib/models/reusable_spec.rb +40 -0
  138. data/spec/lib/models/revocable_spec.rb +8 -6
  139. data/spec/lib/models/scopes_spec.rb +27 -13
  140. data/spec/lib/models/secret_storable_spec.rb +135 -0
  141. data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
  142. data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
  143. data/spec/lib/oauth/base_request_spec.rb +20 -8
  144. data/spec/lib/oauth/base_response_spec.rb +3 -1
  145. data/spec/lib/oauth/client/credentials_spec.rb +24 -22
  146. data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
  147. data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
  148. data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
  149. data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
  150. data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
  151. data/spec/lib/oauth/client_spec.rb +15 -13
  152. data/spec/lib/oauth/code_request_spec.rb +8 -6
  153. data/spec/lib/oauth/code_response_spec.rb +9 -7
  154. data/spec/lib/oauth/error_response_spec.rb +19 -11
  155. data/spec/lib/oauth/error_spec.rb +4 -2
  156. data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
  157. data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
  158. data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
  159. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
  160. data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
  161. data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
  162. data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
  163. data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
  164. data/spec/lib/oauth/scopes_spec.rb +63 -61
  165. data/spec/lib/oauth/token_request_spec.rb +79 -24
  166. data/spec/lib/oauth/token_response_spec.rb +40 -38
  167. data/spec/lib/oauth/token_spec.rb +60 -44
  168. data/spec/lib/request/strategy_spec.rb +3 -1
  169. data/spec/lib/secret_storing/base_spec.rb +60 -0
  170. data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
  171. data/spec/lib/secret_storing/plain_spec.rb +44 -0
  172. data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
  173. data/spec/lib/server_spec.rb +16 -14
  174. data/spec/lib/stale_records_cleaner_spec.rb +17 -17
  175. data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
  176. data/spec/models/doorkeeper/access_token_spec.rb +198 -73
  177. data/spec/models/doorkeeper/application_spec.rb +280 -288
  178. data/spec/requests/applications/applications_request_spec.rb +98 -66
  179. data/spec/requests/applications/authorized_applications_spec.rb +20 -18
  180. data/spec/requests/endpoints/authorization_spec.rb +25 -23
  181. data/spec/requests/endpoints/token_spec.rb +38 -36
  182. data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
  183. data/spec/requests/flows/authorization_code_spec.rb +193 -151
  184. data/spec/requests/flows/client_credentials_spec.rb +54 -52
  185. data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
  186. data/spec/requests/flows/implicit_grant_spec.rb +27 -25
  187. data/spec/requests/flows/password_spec.rb +59 -55
  188. data/spec/requests/flows/refresh_token_spec.rb +45 -43
  189. data/spec/requests/flows/revoke_token_spec.rb +40 -54
  190. data/spec/requests/flows/skip_authorization_spec.rb +23 -21
  191. data/spec/requests/protected_resources/metal_spec.rb +7 -5
  192. data/spec/requests/protected_resources/private_api_spec.rb +35 -33
  193. data/spec/routing/custom_controller_routes_spec.rb +71 -65
  194. data/spec/routing/default_routes_spec.rb +22 -20
  195. data/spec/routing/scoped_routes_spec.rb +20 -18
  196. data/spec/spec_helper.rb +15 -13
  197. data/spec/spec_helper_integration.rb +3 -1
  198. data/spec/support/dependencies/factory_bot.rb +3 -1
  199. data/spec/support/doorkeeper_rspec.rb +3 -1
  200. data/spec/support/helpers/access_token_request_helper.rb +3 -1
  201. data/spec/support/helpers/authorization_request_helper.rb +4 -2
  202. data/spec/support/helpers/config_helper.rb +2 -0
  203. data/spec/support/helpers/model_helper.rb +3 -1
  204. data/spec/support/helpers/request_spec_helper.rb +5 -3
  205. data/spec/support/helpers/url_helper.rb +9 -7
  206. data/spec/support/http_method_shim.rb +4 -9
  207. data/spec/support/orm/active_record.rb +3 -1
  208. data/spec/support/shared/controllers_shared_context.rb +18 -16
  209. data/spec/support/shared/hashing_shared_context.rb +36 -0
  210. data/spec/support/shared/models_shared_examples.rb +12 -10
  211. data/spec/validators/redirect_uri_validator_spec.rb +74 -45
  212. data/spec/version/version_spec.rb +7 -5
  213. metadata +60 -26
  214. data/gemfiles/rails_4_2.gemfile +0 -13
  215. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
@@ -1,113 +1,115 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper::OAuth
4
6
  describe Scopes do
5
- describe '#add' do
6
- it 'allows you to add scopes with symbols' do
7
+ describe "#add" do
8
+ it "allows you to add scopes with symbols" do
7
9
  subject.add :public
8
- expect(subject.all).to eq(['public'])
10
+ expect(subject.all).to eq(["public"])
9
11
  end
10
12
 
11
- it 'allows you to add scopes with strings' do
12
- subject.add 'public'
13
- expect(subject.all).to eq(['public'])
13
+ it "allows you to add scopes with strings" do
14
+ subject.add "public"
15
+ expect(subject.all).to eq(["public"])
14
16
  end
15
17
 
16
- it 'do not add already included scopes' do
18
+ it "do not add already included scopes" do
17
19
  subject.add :public
18
20
  subject.add :public
19
- expect(subject.all).to eq(['public'])
21
+ expect(subject.all).to eq(["public"])
20
22
  end
21
23
  end
22
24
 
23
- describe '#exists' do
25
+ describe "#exists" do
24
26
  before do
25
27
  subject.add :public
26
28
  end
27
29
 
28
- it 'returns true if scope with given name is present' do
29
- expect(subject.exists?('public')).to be_truthy
30
+ it "returns true if scope with given name is present" do
31
+ expect(subject.exists?("public")).to be_truthy
30
32
  end
31
33
 
32
- it 'returns false if scope with given name does not exist' do
33
- expect(subject.exists?('other')).to be_falsey
34
+ it "returns false if scope with given name does not exist" do
35
+ expect(subject.exists?("other")).to be_falsey
34
36
  end
35
37
 
36
- it 'handles symbols' do
38
+ it "handles symbols" do
37
39
  expect(subject.exists?(:public)).to be_truthy
38
40
  expect(subject.exists?(:other)).to be_falsey
39
41
  end
40
42
  end
41
43
 
42
- describe '.from_string' do
43
- let(:string) { 'public write' }
44
+ describe ".from_string" do
45
+ let(:string) { "public write" }
44
46
 
45
47
  subject { Scopes.from_string(string) }
46
48
 
47
49
  it { expect(subject).to be_a(Scopes) }
48
50
 
49
- describe '#all' do
50
- it 'should be an array of the expected scopes' do
51
+ describe "#all" do
52
+ it "should be an array of the expected scopes" do
51
53
  scopes_array = subject.all
52
54
  expect(scopes_array.size).to eq(2)
53
- expect(scopes_array).to include('public')
54
- expect(scopes_array).to include('write')
55
+ expect(scopes_array).to include("public")
56
+ expect(scopes_array).to include("write")
55
57
  end
56
58
  end
57
59
  end
58
60
 
59
- describe '#+' do
60
- it 'can add to another scope object' do
61
- scopes = Scopes.from_string('public') + Scopes.from_string('admin')
61
+ describe "#+" do
62
+ it "can add to another scope object" do
63
+ scopes = Scopes.from_string("public") + Scopes.from_string("admin")
62
64
  expect(scopes.all).to eq(%w[public admin])
63
65
  end
64
66
 
65
- it 'does not change the existing object' do
66
- origin = Scopes.from_string('public')
67
- expect(origin.to_s).to eq('public')
67
+ it "does not change the existing object" do
68
+ origin = Scopes.from_string("public")
69
+ expect(origin.to_s).to eq("public")
68
70
  end
69
71
 
70
- it 'can add an array to a scope object' do
71
- scopes = Scopes.from_string('public') + ['admin']
72
+ it "can add an array to a scope object" do
73
+ scopes = Scopes.from_string("public") + ["admin"]
72
74
  expect(scopes.all).to eq(%w[public admin])
73
75
  end
74
76
 
75
- it 'raises an error if cannot handle addition' do
77
+ it "raises an error if cannot handle addition" do
76
78
  expect do
77
- Scopes.from_string('public') + 'admin'
79
+ Scopes.from_string("public") + "admin"
78
80
  end.to raise_error(NoMethodError)
79
81
  end
80
82
  end
81
83
 
82
- describe '#&' do
83
- it 'can get intersection with another scope object' do
84
- scopes = Scopes.from_string('public admin') & Scopes.from_string('write admin')
84
+ describe "#&" do
85
+ it "can get intersection with another scope object" do
86
+ scopes = Scopes.from_string("public admin") & Scopes.from_string("write admin")
85
87
  expect(scopes.all).to eq(%w[admin])
86
88
  end
87
89
 
88
- it 'does not change the existing object' do
89
- origin = Scopes.from_string('public admin')
90
- origin & Scopes.from_string('write admin')
91
- expect(origin.to_s).to eq('public admin')
90
+ it "does not change the existing object" do
91
+ origin = Scopes.from_string("public admin")
92
+ origin & Scopes.from_string("write admin")
93
+ expect(origin.to_s).to eq("public admin")
92
94
  end
93
95
 
94
- it 'can get intersection with an array' do
95
- scopes = Scopes.from_string('public admin') & %w[write admin]
96
+ it "can get intersection with an array" do
97
+ scopes = Scopes.from_string("public admin") & %w[write admin]
96
98
  expect(scopes.all).to eq(%w[admin])
97
99
  end
98
100
  end
99
101
 
100
- describe '#==' do
101
- it 'is equal to another set of scopes' do
102
- expect(Scopes.from_string('public')).to eq(Scopes.from_string('public'))
102
+ describe "#==" do
103
+ it "is equal to another set of scopes" do
104
+ expect(Scopes.from_string("public")).to eq(Scopes.from_string("public"))
103
105
  end
104
106
 
105
- it 'is equal to another set of scopes with no particular order' do
106
- expect(Scopes.from_string('public write')).to eq(Scopes.from_string('write public'))
107
+ it "is equal to another set of scopes with no particular order" do
108
+ expect(Scopes.from_string("public write")).to eq(Scopes.from_string("write public"))
107
109
  end
108
110
 
109
- it 'differs from another set of scopes when scopes are not the same' do
110
- expect(Scopes.from_string('public write')).not_to eq(Scopes.from_string('write'))
111
+ it "differs from another set of scopes when scopes are not the same" do
112
+ expect(Scopes.from_string("public write")).not_to eq(Scopes.from_string("write"))
111
113
  end
112
114
 
113
115
  it "does not raise an error when compared to a non-enumerable object" do
@@ -115,31 +117,31 @@ module Doorkeeper::OAuth
115
117
  end
116
118
  end
117
119
 
118
- describe '#has_scopes?' do
119
- subject { Scopes.from_string('public admin') }
120
+ describe "#has_scopes?" do
121
+ subject { Scopes.from_string("public admin") }
120
122
 
121
- it 'returns true when at least one scope is included' do
122
- expect(subject.has_scopes?(Scopes.from_string('public'))).to be_truthy
123
+ it "returns true when at least one scope is included" do
124
+ expect(subject.has_scopes?(Scopes.from_string("public"))).to be_truthy
123
125
  end
124
126
 
125
- it 'returns true when all scopes are included' do
126
- expect(subject.has_scopes?(Scopes.from_string('public admin'))).to be_truthy
127
+ it "returns true when all scopes are included" do
128
+ expect(subject.has_scopes?(Scopes.from_string("public admin"))).to be_truthy
127
129
  end
128
130
 
129
- it 'is true if all scopes are included in any order' do
130
- expect(subject.has_scopes?(Scopes.from_string('admin public'))).to be_truthy
131
+ it "is true if all scopes are included in any order" do
132
+ expect(subject.has_scopes?(Scopes.from_string("admin public"))).to be_truthy
131
133
  end
132
134
 
133
- it 'is false if no scopes are included' do
134
- expect(subject.has_scopes?(Scopes.from_string('notexistent'))).to be_falsey
135
+ it "is false if no scopes are included" do
136
+ expect(subject.has_scopes?(Scopes.from_string("notexistent"))).to be_falsey
135
137
  end
136
138
 
137
- it 'returns false when any scope is not included' do
138
- expect(subject.has_scopes?(Scopes.from_string('public nope'))).to be_falsey
139
+ it "returns false when any scope is not included" do
140
+ expect(subject.has_scopes?(Scopes.from_string("public nope"))).to be_falsey
139
141
  end
140
142
 
141
- it 'is false if no scopes are included even for existing ones' do
142
- expect(subject.has_scopes?(Scopes.from_string('public admin notexistent'))).to be_falsey
143
+ it "is false if no scopes are included even for existing ones" do
144
+ expect(subject.has_scopes?(Scopes.from_string("public admin notexistent"))).to be_falsey
143
145
  end
144
146
  end
145
147
  end
@@ -1,18 +1,20 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper::OAuth
4
6
  describe TokenRequest do
5
7
  let :application do
6
- FactoryBot.create(:application, scopes: 'public')
8
+ FactoryBot.create(:application, scopes: "public")
7
9
  end
8
10
 
9
11
  let :pre_auth do
10
12
  double(
11
13
  :pre_auth,
12
14
  client: application,
13
- redirect_uri: 'http://tst.com/cb',
15
+ redirect_uri: "http://tst.com/cb",
14
16
  state: nil,
15
- scopes: Scopes.from_string('public'),
17
+ scopes: Scopes.from_string("public"),
16
18
  error: nil,
17
19
  authorizable?: true
18
20
  )
@@ -26,70 +28,123 @@ module Doorkeeper::OAuth
26
28
  TokenRequest.new(pre_auth, owner)
27
29
  end
28
30
 
29
- it 'creates an access token' do
31
+ it "creates an access token" do
30
32
  expect do
31
33
  subject.authorize
32
34
  end.to change { Doorkeeper::AccessToken.count }.by(1)
33
35
  end
34
36
 
35
- it 'returns a code response' do
37
+ it "returns a code response" do
36
38
  expect(subject.authorize).to be_a(CodeResponse)
37
39
  end
38
40
 
39
- it 'does not create token when not authorizable' do
41
+ it "does not create token when not authorizable" do
40
42
  allow(pre_auth).to receive(:authorizable?).and_return(false)
41
43
  expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
42
44
  end
43
45
 
44
- it 'returns a error response' do
46
+ it "returns a error response" do
45
47
  allow(pre_auth).to receive(:authorizable?).and_return(false)
46
48
  expect(subject.authorize).to be_a(ErrorResponse)
47
49
  end
48
50
 
49
- context 'with custom expirations' do
50
- before do
51
- Doorkeeper.configure do
52
- orm DOORKEEPER_ORM
53
- custom_access_token_expires_in do |context|
54
- context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
51
+ describe "with custom expiration" do
52
+ context "when proper TTL returned" do
53
+ before do
54
+ Doorkeeper.configure do
55
+ orm DOORKEEPER_ORM
56
+ custom_access_token_expires_in do |context|
57
+ context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
58
+ end
55
59
  end
56
60
  end
61
+
62
+ it "should use the custom ttl" do
63
+ subject.authorize
64
+ token = Doorkeeper::AccessToken.first
65
+ expect(token.expires_in).to eq(1234)
66
+ end
57
67
  end
58
68
 
59
- it 'should use the custom ttl' do
60
- subject.authorize
61
- token = Doorkeeper::AccessToken.first
62
- expect(token.expires_in).to eq(1234)
69
+ context "when nil TTL returned" do
70
+ before do
71
+ Doorkeeper.configure do
72
+ orm DOORKEEPER_ORM
73
+ access_token_expires_in 654
74
+ custom_access_token_expires_in do |_context|
75
+ nil
76
+ end
77
+ end
78
+ end
79
+
80
+ it "should fallback to access_token_expires_in" do
81
+ subject.authorize
82
+ token = Doorkeeper::AccessToken.first
83
+ expect(token.expires_in).to eq(654)
84
+ end
85
+ end
86
+
87
+ context "when infinite TTL returned" do
88
+ before do
89
+ Doorkeeper.configure do
90
+ orm DOORKEEPER_ORM
91
+ access_token_expires_in 654
92
+ custom_access_token_expires_in do |_context|
93
+ Float::INFINITY
94
+ end
95
+ end
96
+ end
97
+
98
+ it "should fallback to access_token_expires_in" do
99
+ subject.authorize
100
+ token = Doorkeeper::AccessToken.first
101
+ expect(token.expires_in).to be_nil
102
+ end
63
103
  end
64
104
  end
65
105
 
66
- context 'token reuse' do
67
- it 'creates a new token if there are no matching tokens' do
106
+ context "token reuse" do
107
+ it "creates a new token if there are no matching tokens" do
68
108
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
69
109
  expect do
70
110
  subject.authorize
71
111
  end.to change { Doorkeeper::AccessToken.count }.by(1)
72
112
  end
73
113
 
74
- it 'creates a new token if scopes do not match' do
114
+ it "creates a new token if scopes do not match" do
75
115
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
76
116
  FactoryBot.create(:access_token, application_id: pre_auth.client.id,
77
- resource_owner_id: owner.id, scopes: '')
117
+ resource_owner_id: owner.id, scopes: "")
78
118
  expect do
79
119
  subject.authorize
80
120
  end.to change { Doorkeeper::AccessToken.count }.by(1)
81
121
  end
82
122
 
83
- it 'skips token creation if there is a matching one' do
123
+ it "skips token creation if there is a matching one reusable" do
84
124
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
85
125
  allow(application.scopes).to receive(:has_scopes?).and_return(true)
86
126
  allow(application.scopes).to receive(:all?).and_return(true)
87
127
 
88
128
  FactoryBot.create(:access_token, application_id: pre_auth.client.id,
89
- resource_owner_id: owner.id, scopes: 'public')
129
+ resource_owner_id: owner.id, scopes: "public")
90
130
 
91
131
  expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
92
132
  end
133
+
134
+ it "creates new token if there is a matching one but non reusable" do
135
+ allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
136
+ allow(application.scopes).to receive(:has_scopes?).and_return(true)
137
+ allow(application.scopes).to receive(:all?).and_return(true)
138
+
139
+ FactoryBot.create(:access_token, application_id: pre_auth.client.id,
140
+ resource_owner_id: owner.id, scopes: "public")
141
+
142
+ allow_any_instance_of(Doorkeeper::AccessToken).to receive(:reusable?).and_return(false)
143
+
144
+ expect do
145
+ subject.authorize
146
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
147
+ end
93
148
  end
94
149
  end
95
150
  end
@@ -1,83 +1,85 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper::OAuth
4
6
  describe TokenResponse do
5
7
  subject { TokenResponse.new(double.as_null_object) }
6
8
 
7
- it 'includes access token response headers' do
9
+ it "includes access token response headers" do
8
10
  headers = subject.headers
9
- expect(headers.fetch('Cache-Control')).to eq('no-store')
10
- expect(headers.fetch('Pragma')).to eq('no-cache')
11
+ expect(headers.fetch("Cache-Control")).to eq("no-store")
12
+ expect(headers.fetch("Pragma")).to eq("no-cache")
11
13
  end
12
14
 
13
- it 'status is ok' do
15
+ it "status is ok" do
14
16
  expect(subject.status).to eq(:ok)
15
17
  end
16
18
 
17
- describe '.body' do
19
+ describe ".body" do
18
20
  let(:access_token) do
19
21
  double :access_token,
20
- token: 'some-token',
21
- expires_in: '3600',
22
- expires_in_seconds: '300',
23
- scopes_string: 'two scopes',
24
- refresh_token: 'some-refresh-token',
25
- token_type: 'bearer',
26
- created_at: 0
22
+ plaintext_token: "some-token",
23
+ expires_in: "3600",
24
+ expires_in_seconds: "300",
25
+ scopes_string: "two scopes",
26
+ plaintext_refresh_token: "some-refresh-token",
27
+ token_type: "bearer",
28
+ created_at: 0
27
29
  end
28
30
 
29
31
  subject { TokenResponse.new(access_token).body }
30
32
 
31
- it 'includes :access_token' do
32
- expect(subject['access_token']).to eq('some-token')
33
+ it "includes :access_token" do
34
+ expect(subject["access_token"]).to eq("some-token")
33
35
  end
34
36
 
35
- it 'includes :token_type' do
36
- expect(subject['token_type']).to eq('bearer')
37
+ it "includes :token_type" do
38
+ expect(subject["token_type"]).to eq("bearer")
37
39
  end
38
40
 
39
41
  # expires_in_seconds is returned as `expires_in` in order to match
40
42
  # the OAuth spec (section 4.2.2)
41
- it 'includes :expires_in' do
42
- expect(subject['expires_in']).to eq('300')
43
+ it "includes :expires_in" do
44
+ expect(subject["expires_in"]).to eq("300")
43
45
  end
44
46
 
45
- it 'includes :scope' do
46
- expect(subject['scope']).to eq('two scopes')
47
+ it "includes :scope" do
48
+ expect(subject["scope"]).to eq("two scopes")
47
49
  end
48
50
 
49
- it 'includes :refresh_token' do
50
- expect(subject['refresh_token']).to eq('some-refresh-token')
51
+ it "includes :refresh_token" do
52
+ expect(subject["refresh_token"]).to eq("some-refresh-token")
51
53
  end
52
54
 
53
- it 'includes :created_at' do
54
- expect(subject['created_at']).to eq(0)
55
+ it "includes :created_at" do
56
+ expect(subject["created_at"]).to eq(0)
55
57
  end
56
58
  end
57
59
 
58
- describe '.body filters out empty values' do
60
+ describe ".body filters out empty values" do
59
61
  let(:access_token) do
60
62
  double :access_token,
61
- token: 'some-token',
62
- expires_in_seconds: '',
63
- scopes_string: '',
64
- refresh_token: '',
65
- token_type: 'bearer',
66
- created_at: 0
63
+ plaintext_token: "some-token",
64
+ expires_in_seconds: "",
65
+ scopes_string: "",
66
+ plaintext_refresh_token: "",
67
+ token_type: "bearer",
68
+ created_at: 0
67
69
  end
68
70
 
69
71
  subject { TokenResponse.new(access_token).body }
70
72
 
71
- it 'includes :expires_in' do
72
- expect(subject['expires_in']).to be_nil
73
+ it "includes :expires_in" do
74
+ expect(subject["expires_in"]).to be_nil
73
75
  end
74
76
 
75
- it 'includes :scope' do
76
- expect(subject['scope']).to be_nil
77
+ it "includes :scope" do
78
+ expect(subject["scope"]).to be_nil
77
79
  end
78
80
 
79
- it 'includes :refresh_token' do
80
- expect(subject['refresh_token']).to be_nil
81
+ it "includes :refresh_token" do
82
+ expect(subject["refresh_token"]).to be_nil
81
83
  end
82
84
  end
83
85
  end