doorkeeper 5.3.3 → 5.5.0.rc2

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 (233) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +125 -7
  3. data/README.md +6 -4
  4. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  5. data/app/controllers/doorkeeper/authorizations_controller.rb +46 -16
  6. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  7. data/app/controllers/doorkeeper/tokens_controller.rb +67 -22
  8. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  9. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  10. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  11. data/config/locales/en.yml +6 -2
  12. data/lib/doorkeeper.rb +111 -79
  13. data/lib/doorkeeper/config.rb +148 -94
  14. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  15. data/lib/doorkeeper/config/option.rb +26 -14
  16. data/lib/doorkeeper/config/validations.rb +53 -0
  17. data/lib/doorkeeper/engine.rb +1 -1
  18. data/lib/doorkeeper/grant_flow.rb +45 -0
  19. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  20. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  21. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  22. data/lib/doorkeeper/grape/helpers.rb +1 -1
  23. data/lib/doorkeeper/helpers/controller.rb +8 -4
  24. data/lib/doorkeeper/models/access_grant_mixin.rb +21 -18
  25. data/lib/doorkeeper/models/access_token_mixin.rb +110 -47
  26. data/lib/doorkeeper/models/application_mixin.rb +5 -4
  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 +19 -6
  32. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  33. data/lib/doorkeeper/oauth/authorization/token.rb +18 -16
  34. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  35. data/lib/doorkeeper/oauth/authorization_code_request.rb +17 -14
  36. data/lib/doorkeeper/oauth/base_request.rb +12 -20
  37. data/lib/doorkeeper/oauth/client.rb +1 -1
  38. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  39. data/lib/doorkeeper/oauth/client_credentials/creator.rb +27 -8
  40. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +4 -2
  41. data/lib/doorkeeper/oauth/client_credentials/validator.rb +4 -2
  42. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  43. data/lib/doorkeeper/oauth/code_request.rb +3 -3
  44. data/lib/doorkeeper/oauth/code_response.rb +22 -12
  45. data/lib/doorkeeper/oauth/error_response.rb +6 -7
  46. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
  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 +24 -7
  50. data/lib/doorkeeper/oauth/pre_authorization.rb +63 -32
  51. data/lib/doorkeeper/oauth/refresh_token_request.rb +31 -22
  52. data/lib/doorkeeper/oauth/token.rb +5 -6
  53. data/lib/doorkeeper/oauth/token_introspection.rb +4 -8
  54. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  55. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  56. data/lib/doorkeeper/orm/active_record.rb +14 -7
  57. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +8 -3
  58. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +7 -3
  59. data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -3
  60. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +5 -0
  61. data/lib/doorkeeper/rails/routes.rb +14 -20
  62. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  63. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  64. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  65. data/lib/doorkeeper/request.rb +49 -12
  66. data/lib/doorkeeper/request/refresh_token.rb +2 -1
  67. data/lib/doorkeeper/request/strategy.rb +2 -2
  68. data/lib/doorkeeper/server.rb +4 -4
  69. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  70. data/lib/doorkeeper/version.rb +3 -7
  71. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  72. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  73. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  74. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  75. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  76. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  77. data/lib/generators/doorkeeper/templates/initializer.rb +48 -10
  78. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  79. metadata +30 -300
  80. data/Appraisals +0 -40
  81. data/CODE_OF_CONDUCT.md +0 -46
  82. data/CONTRIBUTING.md +0 -49
  83. data/Dangerfile +0 -67
  84. data/Dockerfile +0 -29
  85. data/Gemfile +0 -25
  86. data/NEWS.md +0 -1
  87. data/RELEASING.md +0 -11
  88. data/Rakefile +0 -28
  89. data/SECURITY.md +0 -15
  90. data/UPGRADE.md +0 -2
  91. data/bin/console +0 -16
  92. data/doorkeeper.gemspec +0 -42
  93. data/gemfiles/rails_5_0.gemfile +0 -18
  94. data/gemfiles/rails_5_1.gemfile +0 -18
  95. data/gemfiles/rails_5_2.gemfile +0 -18
  96. data/gemfiles/rails_6_0.gemfile +0 -18
  97. data/gemfiles/rails_master.gemfile +0 -18
  98. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  99. data/spec/controllers/applications_controller_spec.rb +0 -274
  100. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  101. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  102. data/spec/controllers/token_info_controller_spec.rb +0 -50
  103. data/spec/controllers/tokens_controller_spec.rb +0 -498
  104. data/spec/dummy/Rakefile +0 -9
  105. data/spec/dummy/app/assets/config/manifest.js +0 -2
  106. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  107. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  108. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  109. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  110. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  111. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  112. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  113. data/spec/dummy/app/models/user.rb +0 -7
  114. data/spec/dummy/app/views/home/index.html.erb +0 -0
  115. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  116. data/spec/dummy/config.ru +0 -6
  117. data/spec/dummy/config/application.rb +0 -49
  118. data/spec/dummy/config/boot.rb +0 -7
  119. data/spec/dummy/config/database.yml +0 -15
  120. data/spec/dummy/config/environment.rb +0 -5
  121. data/spec/dummy/config/environments/development.rb +0 -31
  122. data/spec/dummy/config/environments/production.rb +0 -64
  123. data/spec/dummy/config/environments/test.rb +0 -45
  124. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  125. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  126. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  127. data/spec/dummy/config/initializers/session_store.rb +0 -10
  128. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  129. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  130. data/spec/dummy/config/routes.rb +0 -13
  131. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  132. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  133. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  134. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  135. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  136. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  137. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  138. data/spec/dummy/db/schema.rb +0 -68
  139. data/spec/dummy/public/404.html +0 -26
  140. data/spec/dummy/public/422.html +0 -26
  141. data/spec/dummy/public/500.html +0 -26
  142. data/spec/dummy/public/favicon.ico +0 -0
  143. data/spec/dummy/script/rails +0 -9
  144. data/spec/factories.rb +0 -30
  145. data/spec/generators/application_owner_generator_spec.rb +0 -28
  146. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  147. data/spec/generators/install_generator_spec.rb +0 -36
  148. data/spec/generators/migration_generator_spec.rb +0 -28
  149. data/spec/generators/pkce_generator_spec.rb +0 -28
  150. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  151. data/spec/generators/templates/routes.rb +0 -4
  152. data/spec/generators/views_generator_spec.rb +0 -29
  153. data/spec/grape/grape_integration_spec.rb +0 -137
  154. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  155. data/spec/lib/config_spec.rb +0 -809
  156. data/spec/lib/doorkeeper_spec.rb +0 -27
  157. data/spec/lib/models/expirable_spec.rb +0 -61
  158. data/spec/lib/models/reusable_spec.rb +0 -40
  159. data/spec/lib/models/revocable_spec.rb +0 -59
  160. data/spec/lib/models/scopes_spec.rb +0 -53
  161. data/spec/lib/models/secret_storable_spec.rb +0 -135
  162. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  163. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -170
  164. data/spec/lib/oauth/base_request_spec.rb +0 -224
  165. data/spec/lib/oauth/base_response_spec.rb +0 -45
  166. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  167. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -134
  168. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  169. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  170. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  171. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -107
  172. data/spec/lib/oauth/client_spec.rb +0 -38
  173. data/spec/lib/oauth/code_request_spec.rb +0 -46
  174. data/spec/lib/oauth/code_response_spec.rb +0 -32
  175. data/spec/lib/oauth/error_response_spec.rb +0 -64
  176. data/spec/lib/oauth/error_spec.rb +0 -21
  177. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  178. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  179. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  180. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  181. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  182. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  183. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -190
  184. data/spec/lib/oauth/pre_authorization_spec.rb +0 -223
  185. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  186. data/spec/lib/oauth/scopes_spec.rb +0 -146
  187. data/spec/lib/oauth/token_request_spec.rb +0 -157
  188. data/spec/lib/oauth/token_response_spec.rb +0 -84
  189. data/spec/lib/oauth/token_spec.rb +0 -156
  190. data/spec/lib/request/strategy_spec.rb +0 -54
  191. data/spec/lib/secret_storing/base_spec.rb +0 -60
  192. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  193. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  194. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  195. data/spec/lib/server_spec.rb +0 -49
  196. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  197. data/spec/models/doorkeeper/access_grant_spec.rb +0 -161
  198. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  199. data/spec/models/doorkeeper/application_spec.rb +0 -482
  200. data/spec/requests/applications/applications_request_spec.rb +0 -259
  201. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  202. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  203. data/spec/requests/endpoints/token_spec.rb +0 -75
  204. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  205. data/spec/requests/flows/authorization_code_spec.rb +0 -525
  206. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  207. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  208. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  209. data/spec/requests/flows/password_spec.rb +0 -316
  210. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  211. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  212. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  213. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  214. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  215. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  216. data/spec/routing/default_routes_spec.rb +0 -41
  217. data/spec/routing/scoped_routes_spec.rb +0 -47
  218. data/spec/spec_helper.rb +0 -54
  219. data/spec/spec_helper_integration.rb +0 -4
  220. data/spec/support/dependencies/factory_bot.rb +0 -4
  221. data/spec/support/doorkeeper_rspec.rb +0 -22
  222. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  223. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  224. data/spec/support/helpers/config_helper.rb +0 -11
  225. data/spec/support/helpers/model_helper.rb +0 -78
  226. data/spec/support/helpers/request_spec_helper.rb +0 -110
  227. data/spec/support/helpers/url_helper.rb +0 -62
  228. data/spec/support/orm/active_record.rb +0 -5
  229. data/spec/support/shared/controllers_shared_context.rb +0 -133
  230. data/spec/support/shared/hashing_shared_context.rb +0 -36
  231. data/spec/support/shared/models_shared_examples.rb +0 -54
  232. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  233. data/spec/version/version_spec.rb +0 -17
@@ -11,9 +11,8 @@ module Doorkeeper
11
11
  validate :client_match, error: :invalid_grant
12
12
  validate :scope, error: :invalid_scope
13
13
 
14
- attr_accessor :access_token, :client, :credentials, :refresh_token,
15
- :server
16
- attr_reader :missing_param
14
+ attr_reader :access_token, :client, :credentials, :refresh_token
15
+ attr_reader :missing_param
17
16
 
18
17
  def initialize(server, refresh_token, credentials, parameters = {})
19
18
  @server = server
@@ -50,30 +49,40 @@ module Doorkeeper
50
49
  end
51
50
 
52
51
  def create_access_token
53
- @access_token = server_config.access_token_model.create!(access_token_attributes)
54
- end
52
+ attributes = {}
55
53
 
56
- def access_token_attributes
57
- {
58
- application_id: refresh_token.application_id,
59
- resource_owner_id: refresh_token.resource_owner_id,
60
- scopes: scopes.to_s,
61
- expires_in: access_token_expires_in,
62
- use_refresh_token: true,
63
- }.tap do |attributes|
64
- if refresh_token_revoked_on_use?
65
- attributes[:previous_refresh_token] = refresh_token.refresh_token
54
+ resource_owner =
55
+ if Doorkeeper.config.polymorphic_resource_owner?
56
+ refresh_token.resource_owner
57
+ else
58
+ refresh_token.resource_owner_id
66
59
  end
60
+
61
+ if refresh_token_revoked_on_use?
62
+ attributes[:previous_refresh_token] = refresh_token.refresh_token
67
63
  end
68
- end
69
64
 
70
- def access_token_expires_in
71
- context = Authorization::Token.build_context(
72
- client,
73
- Doorkeeper::OAuth::REFRESH_TOKEN,
74
- scopes,
65
+ # RFC6749
66
+ # 1.5. Refresh Token
67
+ #
68
+ # Refresh tokens are issued to the client by the authorization server and are
69
+ # used to obtain a new access token when the current access token
70
+ # becomes invalid or expires, or to obtain additional access tokens
71
+ # with identical or narrower scope (access tokens may have a shorter
72
+ # lifetime and fewer permissions than authorized by the resource
73
+ # owner).
74
+ #
75
+ # Here we assume that TTL of the token received after refreshing should be
76
+ # the same as that of the original token.
77
+ #
78
+ @access_token = server_config.access_token_model.create_for(
79
+ application: refresh_token.application,
80
+ resource_owner: resource_owner,
81
+ scopes: scopes,
82
+ expires_in: refresh_token.expires_in,
83
+ use_refresh_token: true,
84
+ **attributes,
75
85
  )
76
- Authorization::Token.access_token_expires_in(server, context)
77
86
  end
78
87
 
79
88
  def validate_token_presence
@@ -8,15 +8,14 @@ module Doorkeeper
8
8
  methods.inject(nil) do |_, method|
9
9
  method = self.method(method) if method.is_a?(Symbol)
10
10
  credentials = method.call(request)
11
- break credentials unless credentials.blank?
11
+ break credentials if credentials.present?
12
12
  end
13
13
  end
14
14
 
15
15
  def authenticate(request, *methods)
16
16
  if (token = from_request(request, *methods))
17
17
  access_token = Doorkeeper.config.access_token_model.by_token(token)
18
- refresh_token_enabled = Doorkeeper.config.refresh_token_enabled?
19
- if access_token.present? && refresh_token_enabled
18
+ if access_token.present? && Doorkeeper.config.refresh_token_enabled?
20
19
  access_token.revoke_previous_refresh_token!
21
20
  end
22
21
  access_token
@@ -33,13 +32,13 @@ module Doorkeeper
33
32
 
34
33
  def from_bearer_authorization(request)
35
34
  pattern = /^Bearer /i
36
- header = request.authorization
35
+ header = request.authorization
37
36
  token_from_header(header, pattern) if match?(header, pattern)
38
37
  end
39
38
 
40
39
  def from_basic_authorization(request)
41
40
  pattern = /^Basic /i
42
- header = request.authorization
41
+ header = request.authorization
43
42
  token_from_basic_header(header, pattern) if match?(header, pattern)
44
43
  end
45
44
 
@@ -55,7 +54,7 @@ module Doorkeeper
55
54
  end
56
55
 
57
56
  def token_from_header(header, pattern)
58
- header.gsub pattern, ""
57
+ header.gsub(pattern, "")
59
58
  end
60
59
 
61
60
  def match?(header, pattern)
@@ -6,9 +6,6 @@ module Doorkeeper
6
6
  #
7
7
  # @see https://tools.ietf.org/html/rfc7662
8
8
  class TokenIntrospection
9
- attr_reader :server, :token
10
- attr_reader :error, :invalid_request_reason
11
-
12
9
  def initialize(server, token)
13
10
  @server = server
14
11
  @token = token
@@ -38,6 +35,9 @@ module Doorkeeper
38
35
 
39
36
  private
40
37
 
38
+ attr_reader :server, :token
39
+ attr_reader :error, :invalid_request_reason
40
+
41
41
  # If the protected resource uses OAuth 2.0 client credentials to
42
42
  # authenticate to the introspection endpoint and its credentials are
43
43
  # invalid, the authorization server responds with an HTTP 401
@@ -179,11 +179,7 @@ module Doorkeeper
179
179
  allow_introspection = Doorkeeper.config.allow_token_introspection
180
180
  return allow_introspection unless allow_introspection.respond_to?(:call)
181
181
 
182
- allow_introspection.call(
183
- @token,
184
- auth_client,
185
- auth_token,
186
- )
182
+ allow_introspection.call(@token, auth_client, auth_token)
187
183
  end
188
184
 
189
185
  # Allows to customize introspection response.
@@ -3,16 +3,16 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class TokenRequest
6
- attr_accessor :pre_auth, :resource_owner
6
+ attr_reader :pre_auth, :resource_owner
7
7
 
8
8
  def initialize(pre_auth, resource_owner)
9
- @pre_auth = pre_auth
9
+ @pre_auth = pre_auth
10
10
  @resource_owner = resource_owner
11
11
  end
12
12
 
13
13
  def authorize
14
14
  auth = Authorization::Token.new(pre_auth, resource_owner)
15
- auth.issue_token
15
+ auth.issue_token!
16
16
  CodeResponse.new(pre_auth, auth, response_on_fragment: true)
17
17
  end
18
18
 
@@ -3,7 +3,7 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class TokenResponse
6
- attr_accessor :token
6
+ attr_reader :token
7
7
 
8
8
  def initialize(token)
9
9
  @token = token
@@ -20,9 +20,8 @@ module Doorkeeper
20
20
  require "doorkeeper/orm/active_record/access_token"
21
21
  require "doorkeeper/orm/active_record/application"
22
22
 
23
- if Doorkeeper.config.active_record_options[:establish_connection]
23
+ if (options = Doorkeeper.config.active_record_options[:establish_connection])
24
24
  Doorkeeper::Orm::ActiveRecord.models.each do |model|
25
- options = Doorkeeper.config.active_record_options[:establish_connection]
26
25
  model.establish_connection(options)
27
26
  end
28
27
  end
@@ -33,19 +32,27 @@ module Doorkeeper
33
32
  lazy_load do
34
33
  require "doorkeeper/models/concerns/ownership"
35
34
 
36
- Doorkeeper.config.application_model.send :include, Doorkeeper::Models::Ownership
35
+ Doorkeeper.config.application_model.include(Doorkeeper::Models::Ownership)
37
36
  end
38
37
  end
39
38
 
40
39
  def self.lazy_load(&block)
41
- ActiveSupport.on_load(:active_record, {}, &block)
40
+ # ActiveSupport has no public interface to check if something
41
+ # already lazy-loaded :(
42
+ loaded = ActiveSupport.instance_variable_get(:"@loaded") || {}
43
+
44
+ if loaded.key?(:active_record)
45
+ block.call
46
+ else
47
+ ActiveSupport.on_load(:active_record, {}, &block)
48
+ end
42
49
  end
43
50
 
44
51
  def self.models
45
52
  [
46
- Doorkeeper::AccessGrant,
47
- Doorkeeper::AccessToken,
48
- Doorkeeper::Application,
53
+ Doorkeeper.config.access_grant_model,
54
+ Doorkeeper.config.access_token_model,
55
+ Doorkeeper.config.application_model,
49
56
  ]
50
57
  end
51
58
  end
@@ -9,12 +9,17 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
9
9
 
10
10
  include ::Doorkeeper::AccessGrantMixin
11
11
 
12
- belongs_to :application, class_name: Doorkeeper.config.application_class,
12
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
13
13
  optional: true,
14
14
  inverse_of: :access_grants
15
15
 
16
- validates :resource_owner_id,
17
- :application_id,
16
+ if Doorkeeper.config.polymorphic_resource_owner?
17
+ belongs_to :resource_owner, polymorphic: true, optional: false
18
+ else
19
+ validates :resource_owner_id, presence: true
20
+ end
21
+
22
+ validates :application_id,
18
23
  :token,
19
24
  :expires_in,
20
25
  :redirect_uri,
@@ -9,10 +9,14 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
9
9
 
10
10
  include ::Doorkeeper::AccessTokenMixin
11
11
 
12
- belongs_to :application, class_name: Doorkeeper.config.application_class,
12
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
13
13
  inverse_of: :access_tokens,
14
14
  optional: true
15
15
 
16
+ if Doorkeeper.config.polymorphic_resource_owner?
17
+ belongs_to :resource_owner, polymorphic: true, optional: true
18
+ end
19
+
16
20
  validates :token, presence: true, uniqueness: { case_sensitive: true }
17
21
  validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
18
22
 
@@ -25,7 +29,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
25
29
  on: :create, if: :use_refresh_token?
26
30
  end
27
31
 
28
- class_methods do
32
+ module ClassMethods
29
33
  # Searches for not revoked Access Tokens associated with the
30
34
  # specific Resource Owner.
31
35
  #
@@ -36,7 +40,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
36
40
  # active Access Tokens for Resource Owner
37
41
  #
38
42
  def active_for(resource_owner)
39
- where(resource_owner_id: resource_owner.id, revoked_at: nil)
43
+ by_resource_owner(resource_owner).where(revoked_at: nil)
40
44
  end
41
45
 
42
46
  def refresh_token_revoked_on_use?
@@ -137,9 +137,9 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
137
137
  only = Array.wrap(opts[:only]).map(&:to_s)
138
138
 
139
139
  only = if only.blank?
140
- serializable_attributes
140
+ client_serializable_attributes
141
141
  else
142
- only & serializable_attributes
142
+ only & client_serializable_attributes
143
143
  end
144
144
 
145
145
  only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
@@ -150,7 +150,10 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
150
150
  # Override this method if you need additional attributes to be serialized.
151
151
  #
152
152
  # @return [Array<String>] collection of serializable attributes
153
- def serializable_attributes
153
+ #
154
+ # NOTE: `serializable_attributes` method already taken by Rails >= 6
155
+ #
156
+ def client_serializable_attributes
154
157
  attributes = %w[id name created_at]
155
158
  attributes << "uid" unless confidential?
156
159
  attributes
@@ -21,6 +21,7 @@ module Doorkeeper
21
21
  record.errors.add(attribute, :unspecified_scheme) if unspecified_scheme?(uri)
22
22
  record.errors.add(attribute, :relative_uri) if relative_uri?(uri)
23
23
  record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
24
+ record.errors.add(attribute, :invalid_uri) if unspecified_host?(uri)
24
25
  end
25
26
  end
26
27
  rescue URI::InvalidURIError
@@ -43,6 +44,10 @@ module Doorkeeper
43
44
  %w[localhost].include?(uri.try(:scheme))
44
45
  end
45
46
 
47
+ def unspecified_host?(uri)
48
+ uri.is_a?(URI::HTTP) && uri.host.nil?
49
+ end
50
+
46
51
  def relative_uri?(uri)
47
52
  uri.scheme.nil? && uri.host.nil?
48
53
  end
@@ -2,31 +2,33 @@
2
2
 
3
3
  require "doorkeeper/rails/routes/mapping"
4
4
  require "doorkeeper/rails/routes/mapper"
5
+ require "doorkeeper/rails/routes/abstract_router"
6
+ require "doorkeeper/rails/routes/registry"
5
7
 
6
8
  module Doorkeeper
7
9
  module Rails
8
10
  class Routes # :nodoc:
9
- mattr_reader :mapping do
10
- {}
11
- end
12
-
13
11
  module Helper
14
12
  def use_doorkeeper(options = {}, &block)
15
13
  Doorkeeper::Rails::Routes.new(self, &block).generate_routes!(options)
16
14
  end
17
15
  end
18
16
 
19
- def self.install!
20
- ActionDispatch::Routing::Mapper.include Doorkeeper::Rails::Routes::Helper
17
+ include AbstractRouter
18
+ extend Registry
19
+
20
+ mattr_reader :mapping do
21
+ {}
21
22
  end
22
23
 
23
- attr_reader :routes
24
+ def self.install!
25
+ ActionDispatch::Routing::Mapper.include Doorkeeper::Rails::Routes::Helper
24
26
 
25
- def initialize(routes, &block)
26
- @routes = routes
27
- @mapping = Mapper.new.map(&block)
27
+ registered_routes.each(&:install!)
28
+ end
28
29
 
29
- @mapping.skips.push(:applications, :authorized_applications) if Doorkeeper.config.api_only
30
+ def initialize(routes, mapper = Mapper.new, &block)
31
+ super
30
32
  end
31
33
 
32
34
  def generate_routes!(options)
@@ -34,7 +36,7 @@ module Doorkeeper
34
36
  map_route(:authorizations, :authorization_routes)
35
37
  map_route(:tokens, :token_routes)
36
38
  map_route(:tokens, :revoke_routes)
37
- map_route(:tokens, :introspect_routes)
39
+ map_route(:tokens, :introspect_routes) unless Doorkeeper.config.allow_token_introspection.is_a?(FalseClass)
38
40
  map_route(:applications, :application_routes)
39
41
  map_route(:authorized_applications, :authorized_applications_routes)
40
42
  map_route(:token_info, :token_info_routes)
@@ -43,14 +45,6 @@ module Doorkeeper
43
45
 
44
46
  private
45
47
 
46
- def map_route(name, method)
47
- return if @mapping.skipped?(name)
48
-
49
- send(method, @mapping[name])
50
-
51
- mapping[name] = @mapping[name]
52
- end
53
-
54
48
  def authorization_routes(mapping)
55
49
  routes.resource(
56
50
  :authorization,
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Rails
5
+ # Abstract router module that implements base behavior
6
+ # for generating and mapping Rails routes.
7
+ #
8
+ # Could be reused in Doorkeeper extensions.
9
+ #
10
+ module AbstractRouter
11
+ extend ActiveSupport::Concern
12
+
13
+ attr_reader :routes
14
+
15
+ def initialize(routes, mapper = Mapper.new, &block)
16
+ @routes = routes
17
+ @mapping = mapper.map(&block)
18
+ end
19
+
20
+ def generate_routes!(**_options)
21
+ raise NotImplementedError, "must be redefined for #{self.class.name}!"
22
+ end
23
+
24
+ private
25
+
26
+ def map_route(name, method)
27
+ return if @mapping.skipped?(name)
28
+
29
+ send(method, @mapping[name])
30
+
31
+ mapping[name] = @mapping[name]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -4,8 +4,8 @@ module Doorkeeper
4
4
  module Rails
5
5
  class Routes # :nodoc:
6
6
  class Mapper
7
- def initialize
8
- @mapping = Mapping.new
7
+ def initialize(mapping = Mapping.new)
8
+ @mapping = mapping
9
9
  end
10
10
 
11
11
  def map(&block)
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Rails
5
+ class Routes
6
+ # Thread-safe registry of any Doorkeeper additional routes.
7
+ # Used to allow implementing of Doorkeeper extensions that must
8
+ # use their own routes.
9
+ #
10
+ module Registry
11
+ ROUTES_ACCESS_LOCK = Mutex.new
12
+ ROUTES_DEFINITION_LOCK = Mutex.new
13
+
14
+ InvalidRouterClass = Class.new(StandardError)
15
+
16
+ # Collection of additional registered routes for Doorkeeper.
17
+ #
18
+ # @return [Array<Object>] set of registered routes
19
+ #
20
+ def registered_routes
21
+ ROUTES_DEFINITION_LOCK.synchronize do
22
+ @registered_routes ||= Set.new
23
+ end
24
+ end
25
+
26
+ # Registers additional routes in the Doorkeeper registry
27
+ #
28
+ # @param [Object] routes
29
+ # routes class
30
+ #
31
+ def register_routes(routes)
32
+ if !routes.is_a?(Module) || !(routes < AbstractRouter)
33
+ raise InvalidRouterClass, "routes class must include Doorkeeper::Rails::AbstractRouter"
34
+ end
35
+
36
+ ROUTES_ACCESS_LOCK.synchronize do
37
+ registered_routes << routes
38
+ end
39
+ end
40
+
41
+ alias register register_routes
42
+ end
43
+ end
44
+ end
45
+ end