doorkeeper 4.2.5 → 5.0.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/.github/ISSUE_TEMPLATE.md +25 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  4. data/.gitignore +2 -1
  5. data/.gitlab-ci.yml +16 -0
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +19 -4
  9. data/Appraisals +8 -4
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/Gemfile +1 -1
  12. data/NEWS.md +115 -0
  13. data/README.md +175 -39
  14. data/RELEASING.md +5 -12
  15. data/Rakefile +6 -0
  16. data/SECURITY.md +15 -0
  17. data/UPGRADE.md +2 -0
  18. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  19. data/app/controllers/doorkeeper/application_controller.rb +2 -5
  20. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  21. data/app/controllers/doorkeeper/applications_controller.rb +47 -13
  22. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  23. data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
  24. data/app/controllers/doorkeeper/tokens_controller.rb +24 -17
  25. data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
  26. data/app/validators/redirect_uri_validator.rb +13 -2
  27. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  28. data/app/views/doorkeeper/applications/_form.html.erb +31 -19
  29. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  30. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  31. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  32. data/app/views/doorkeeper/applications/show.html.erb +8 -5
  33. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  34. data/app/views/doorkeeper/authorizations/new.html.erb +5 -1
  35. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  36. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  37. data/config/locales/en.yml +19 -6
  38. data/doorkeeper.gemspec +20 -20
  39. data/gemfiles/rails_4_2.gemfile +6 -4
  40. data/gemfiles/rails_5_0.gemfile +4 -4
  41. data/gemfiles/rails_5_1.gemfile +6 -7
  42. data/gemfiles/rails_5_2.gemfile +12 -0
  43. data/gemfiles/rails_master.gemfile +17 -0
  44. data/lib/doorkeeper/config.rb +123 -71
  45. data/lib/doorkeeper/engine.rb +7 -3
  46. data/lib/doorkeeper/errors.rb +20 -5
  47. data/lib/doorkeeper/grape/helpers.rb +14 -9
  48. data/lib/doorkeeper/helpers/controller.rb +16 -22
  49. data/lib/doorkeeper/models/access_grant_mixin.rb +67 -23
  50. data/lib/doorkeeper/models/access_token_mixin.rb +54 -55
  51. data/lib/doorkeeper/models/application_mixin.rb +16 -30
  52. data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
  53. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  54. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  55. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  56. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  57. data/lib/doorkeeper/oauth/authorization/token.rb +46 -20
  58. data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
  59. data/lib/doorkeeper/oauth/base_request.rb +23 -7
  60. data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
  61. data/lib/doorkeeper/oauth/client.rb +2 -4
  62. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
  63. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
  64. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
  65. data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +11 -4
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
  75. data/lib/doorkeeper/oauth/scopes.rb +19 -9
  76. data/lib/doorkeeper/oauth/token.rb +6 -3
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  79. data/lib/doorkeeper/oauth.rb +13 -0
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
  82. data/lib/doorkeeper/orm/active_record/application.rb +45 -0
  83. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  84. data/lib/doorkeeper/orm/active_record.rb +21 -8
  85. data/lib/doorkeeper/rails/helpers.rb +7 -10
  86. data/lib/doorkeeper/rails/routes.rb +21 -7
  87. data/lib/doorkeeper/rake/db.rake +40 -0
  88. data/lib/doorkeeper/rake/setup.rake +6 -0
  89. data/lib/doorkeeper/rake.rb +14 -0
  90. data/lib/doorkeeper/request/authorization_code.rb +0 -2
  91. data/lib/doorkeeper/request/client_credentials.rb +0 -2
  92. data/lib/doorkeeper/request/code.rb +0 -2
  93. data/lib/doorkeeper/request/password.rb +1 -13
  94. data/lib/doorkeeper/request/refresh_token.rb +0 -2
  95. data/lib/doorkeeper/request/token.rb +0 -2
  96. data/lib/doorkeeper/request.rb +29 -30
  97. data/lib/doorkeeper/validations.rb +3 -2
  98. data/lib/doorkeeper/version.rb +14 -1
  99. data/lib/doorkeeper.rb +21 -17
  100. data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
  101. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  102. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  103. data/lib/generators/doorkeeper/migration_generator.rb +26 -9
  104. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  105. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
  106. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  107. data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
  108. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
  109. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  110. data/lib/generators/doorkeeper/templates/initializer.rb +104 -12
  111. data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
  112. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  113. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  114. data/spec/controllers/applications_controller_spec.rb +141 -17
  115. data/spec/controllers/authorizations_controller_spec.rb +304 -27
  116. data/spec/controllers/protected_resources_controller_spec.rb +44 -35
  117. data/spec/controllers/token_info_controller_spec.rb +17 -21
  118. data/spec/controllers/tokens_controller_spec.rb +201 -17
  119. data/spec/dummy/app/assets/config/manifest.js +2 -0
  120. data/spec/dummy/config/environments/test.rb +4 -5
  121. data/spec/dummy/config/initializers/doorkeeper.rb +23 -2
  122. data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
  123. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  124. data/spec/dummy/config/routes.rb +3 -42
  125. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  126. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  127. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
  128. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
  129. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
  130. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  131. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
  132. data/spec/dummy/db/schema.rb +38 -37
  133. data/spec/factories.rb +1 -1
  134. data/spec/generators/application_owner_generator_spec.rb +25 -6
  135. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  136. data/spec/generators/install_generator_spec.rb +1 -1
  137. data/spec/generators/migration_generator_spec.rb +25 -4
  138. data/spec/generators/pkce_generator_spec.rb +43 -0
  139. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  140. data/spec/generators/views_generator_spec.rb +1 -1
  141. data/spec/grape/grape_integration_spec.rb +135 -0
  142. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
  143. data/spec/lib/config_spec.rb +199 -22
  144. data/spec/lib/doorkeeper_spec.rb +1 -126
  145. data/spec/lib/models/expirable_spec.rb +0 -4
  146. data/spec/lib/models/revocable_spec.rb +2 -4
  147. data/spec/lib/models/scopes_spec.rb +0 -4
  148. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  149. data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
  150. data/spec/lib/oauth/base_request_spec.rb +43 -10
  151. data/spec/lib/oauth/base_response_spec.rb +1 -1
  152. data/spec/lib/oauth/client/credentials_spec.rb +5 -5
  153. data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
  154. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  155. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  156. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  157. data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
  158. data/spec/lib/oauth/client_spec.rb +0 -3
  159. data/spec/lib/oauth/code_request_spec.rb +5 -5
  160. data/spec/lib/oauth/error_response_spec.rb +0 -3
  161. data/spec/lib/oauth/error_spec.rb +1 -3
  162. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  163. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  164. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  165. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
  166. data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
  167. data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
  168. data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
  169. data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
  170. data/spec/lib/oauth/scopes_spec.rb +28 -4
  171. data/spec/lib/oauth/token_request_spec.rb +10 -13
  172. data/spec/lib/oauth/token_response_spec.rb +0 -1
  173. data/spec/lib/oauth/token_spec.rb +37 -14
  174. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  175. data/spec/lib/request/strategy_spec.rb +0 -1
  176. data/spec/lib/server_spec.rb +10 -0
  177. data/spec/models/doorkeeper/access_grant_spec.rb +45 -2
  178. data/spec/models/doorkeeper/access_token_spec.rb +132 -64
  179. data/spec/models/doorkeeper/application_spec.rb +114 -23
  180. data/spec/requests/applications/applications_request_spec.rb +139 -6
  181. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  182. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  183. data/spec/requests/endpoints/token_spec.rb +15 -6
  184. data/spec/requests/flows/authorization_code_errors_spec.rb +12 -2
  185. data/spec/requests/flows/authorization_code_spec.rb +199 -2
  186. data/spec/requests/flows/client_credentials_spec.rb +73 -5
  187. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  188. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  189. data/spec/requests/flows/password_spec.rb +160 -24
  190. data/spec/requests/flows/refresh_token_spec.rb +6 -6
  191. data/spec/requests/flows/revoke_token_spec.rb +26 -26
  192. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  193. data/spec/requests/protected_resources/metal_spec.rb +2 -2
  194. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  195. data/spec/routing/custom_controller_routes_spec.rb +63 -7
  196. data/spec/routing/default_routes_spec.rb +6 -2
  197. data/spec/routing/scoped_routes_spec.rb +16 -2
  198. data/spec/spec_helper.rb +54 -3
  199. data/spec/spec_helper_integration.rb +2 -64
  200. data/spec/support/dependencies/factory_bot.rb +2 -0
  201. data/spec/support/doorkeeper_rspec.rb +19 -0
  202. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  203. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  204. data/spec/support/helpers/model_helper.rb +9 -4
  205. data/spec/support/helpers/request_spec_helper.rb +18 -6
  206. data/spec/support/helpers/url_helper.rb +15 -10
  207. data/spec/support/http_method_shim.rb +12 -16
  208. data/spec/support/shared/controllers_shared_context.rb +2 -6
  209. data/spec/support/shared/models_shared_examples.rb +4 -4
  210. data/spec/validators/redirect_uri_validator_spec.rb +58 -7
  211. data/spec/version/version_spec.rb +15 -0
  212. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  213. metadata +75 -33
  214. data/spec/controllers/application_metal_controller.rb +0 -10
  215. data/spec/support/dependencies/factory_girl.rb +0 -2
@@ -23,9 +23,11 @@ module Doorkeeper
23
23
  end
24
24
 
25
25
  def headers
26
- { 'Cache-Control' => 'no-store',
26
+ {
27
+ 'Cache-Control' => 'no-store',
27
28
  'Pragma' => 'no-cache',
28
- 'Content-Type' => 'application/json; charset=utf-8' }
29
+ 'Content-Type' => 'application/json; charset=utf-8'
30
+ }
29
31
  end
30
32
  end
31
33
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ GRANT_TYPES = [
6
+ AUTHORIZATION_CODE = 'authorization_code'.freeze,
7
+ IMPLICIT = 'implicit'.freeze,
8
+ PASSWORD = 'password'.freeze,
9
+ CLIENT_CREDENTIALS = 'client_credentials'.freeze,
10
+ REFRESH_TOKEN = 'refresh_token'.freeze
11
+ ].freeze
12
+ end
13
+ end
@@ -3,5 +3,32 @@ module Doorkeeper
3
3
  self.table_name = "#{table_name_prefix}oauth_access_grants#{table_name_suffix}".to_sym
4
4
 
5
5
  include AccessGrantMixin
6
+ include ActiveModel::MassAssignmentSecurity if defined?(::ProtectedAttributes)
7
+
8
+ belongs_to_options = {
9
+ class_name: 'Doorkeeper::Application',
10
+ inverse_of: :access_grants
11
+ }
12
+
13
+ if defined?(ActiveRecord::Base) && ActiveRecord::VERSION::MAJOR >= 5
14
+ belongs_to_options[:optional] = true
15
+ end
16
+
17
+ belongs_to :application, belongs_to_options
18
+
19
+ validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, presence: true
20
+ validates :token, uniqueness: true
21
+
22
+ before_validation :generate_token, on: :create
23
+
24
+ private
25
+
26
+ # Generates token value with UniqueToken class.
27
+ #
28
+ # @return [String] token value
29
+ #
30
+ def generate_token
31
+ self.token = UniqueToken.generate
32
+ end
6
33
  end
7
34
  end
@@ -3,18 +3,29 @@ module Doorkeeper
3
3
  self.table_name = "#{table_name_prefix}oauth_access_tokens#{table_name_suffix}".to_sym
4
4
 
5
5
  include AccessTokenMixin
6
+ include ActiveModel::MassAssignmentSecurity if defined?(::ProtectedAttributes)
6
7
 
7
- # Deletes all the Access Tokens created for the specific
8
- # Application and Resource Owner.
9
- #
10
- # @param application_id [Integer] Application ID
11
- # @param resource_owner [ActiveRecord::Base] Resource Owner model instance
12
- #
13
- def self.delete_all_for(application_id, resource_owner)
14
- where(application_id: application_id,
15
- resource_owner_id: resource_owner.id).delete_all
8
+ belongs_to_options = {
9
+ class_name: 'Doorkeeper::Application',
10
+ inverse_of: :access_tokens
11
+ }
12
+
13
+ if defined?(ActiveRecord::Base) && ActiveRecord::VERSION::MAJOR >= 5
14
+ belongs_to_options[:optional] = true
16
15
  end
17
- private_class_method :delete_all_for
16
+
17
+ belongs_to :application, belongs_to_options
18
+
19
+ validates :token, presence: true, uniqueness: true
20
+ validates :refresh_token, uniqueness: true, if: :use_refresh_token?
21
+
22
+ # @attr_writer [Boolean, nil] use_refresh_token
23
+ # indicates the possibility of using refresh token
24
+ attr_writer :use_refresh_token
25
+
26
+ before_validation :generate_token, on: :create
27
+ before_validation :generate_refresh_token,
28
+ on: :create, if: :use_refresh_token?
18
29
 
19
30
  # Searches for not revoked Access Tokens associated with the
20
31
  # specific Resource Owner.
@@ -29,18 +40,8 @@ module Doorkeeper
29
40
  where(resource_owner_id: resource_owner.id, revoked_at: nil)
30
41
  end
31
42
 
32
- # ORM-specific order method.
33
- def self.order_method
34
- :order
35
- end
36
-
37
43
  def self.refresh_token_revoked_on_use?
38
44
  column_names.include?('previous_refresh_token')
39
45
  end
40
-
41
- # ORM-specific DESC order for `:created_at` column.
42
- def self.created_at_desc
43
- 'created_at desc'
44
- end
45
46
  end
46
47
  end
@@ -3,6 +3,19 @@ module Doorkeeper
3
3
  self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}".to_sym
4
4
 
5
5
  include ApplicationMixin
6
+ include ActiveModel::MassAssignmentSecurity if defined?(::ProtectedAttributes)
7
+
8
+ has_many :access_grants, dependent: :delete_all, class_name: 'Doorkeeper::AccessGrant'
9
+ has_many :access_tokens, dependent: :delete_all, class_name: 'Doorkeeper::AccessToken'
10
+
11
+ validates :name, :secret, :uid, presence: true
12
+ validates :uid, uniqueness: true
13
+ validates :redirect_uri, redirect_uri: true
14
+ validates :confidential, inclusion: { in: [true, false] }
15
+
16
+ validate :scopes_match_configured, if: :enforce_scopes?
17
+
18
+ before_validation :generate_uid, :generate_secret, on: :create
6
19
 
7
20
  has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: 'AccessToken'
8
21
  has_many :authorized_applications, through: :authorized_tokens, source: :application
@@ -20,5 +33,37 @@ module Doorkeeper
20
33
  resource_access_tokens = AccessToken.active_for(resource_owner)
21
34
  where(id: resource_access_tokens.select(:application_id).distinct)
22
35
  end
36
+
37
+ # Revokes AccessToken and AccessGrant records that have not been revoked and
38
+ # associated with the specific Application and Resource Owner.
39
+ #
40
+ # @param resource_owner [ActiveRecord::Base]
41
+ # instance of the Resource Owner model
42
+ #
43
+ def self.revoke_tokens_and_grants_for(id, resource_owner)
44
+ AccessToken.revoke_all_for(id, resource_owner)
45
+ AccessGrant.revoke_all_for(id, resource_owner)
46
+ end
47
+
48
+ private
49
+
50
+ def generate_uid
51
+ self.uid = UniqueToken.generate if uid.blank?
52
+ end
53
+
54
+ def generate_secret
55
+ self.secret = UniqueToken.generate if secret.blank?
56
+ end
57
+
58
+ def scopes_match_configured
59
+ if scopes.present? &&
60
+ !ScopeChecker.valid?(scopes.to_s, Doorkeeper.configuration.scopes)
61
+ errors.add(:scopes, :not_match_configured)
62
+ end
63
+ end
64
+
65
+ def enforce_scopes?
66
+ Doorkeeper.configuration.enforce_configured_scopes?
67
+ end
23
68
  end
24
69
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Orm
5
+ module ActiveRecord
6
+ class StaleRecordsCleaner
7
+ def initialize(base_scope)
8
+ @base_scope = base_scope
9
+ end
10
+
11
+ def clean_revoked
12
+ table = @base_scope.arel_table
13
+ @base_scope.where.not(revoked_at: nil)
14
+ .where(table[:revoked_at].lt(Time.current))
15
+ .delete_all
16
+ end
17
+
18
+ def clean_expired(ttl)
19
+ table = @base_scope.arel_table
20
+ @base_scope.where(table[:created_at].lt(Time.current - ttl))
21
+ .delete_all
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,22 +1,35 @@
1
+ require 'active_support/lazy_load_hooks'
2
+
3
+ require 'doorkeeper/orm/active_record/stale_records_cleaner'
4
+
1
5
  module Doorkeeper
2
6
  module Orm
3
7
  module ActiveRecord
4
8
  def self.initialize_models!
5
- require 'doorkeeper/orm/active_record/access_grant'
6
- require 'doorkeeper/orm/active_record/access_token'
7
- require 'doorkeeper/orm/active_record/application'
9
+ lazy_load do
10
+ require 'doorkeeper/orm/active_record/access_grant'
11
+ require 'doorkeeper/orm/active_record/access_token'
12
+ require 'doorkeeper/orm/active_record/application'
8
13
 
9
- if Doorkeeper.configuration.active_record_options[:establish_connection]
10
- [Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application].each do |c|
11
- c.send :establish_connection, Doorkeeper.configuration.active_record_options[:establish_connection]
14
+ if Doorkeeper.configuration.active_record_options[:establish_connection]
15
+ [Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application].each do |model|
16
+ options = Doorkeeper.configuration.active_record_options[:establish_connection]
17
+ model.establish_connection(options)
18
+ end
12
19
  end
13
20
  end
14
21
  end
15
22
 
16
23
  def self.initialize_application_owner!
17
- require 'doorkeeper/models/concerns/ownership'
24
+ lazy_load do
25
+ require 'doorkeeper/models/concerns/ownership'
26
+
27
+ Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
28
+ end
29
+ end
18
30
 
19
- Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
31
+ def self.lazy_load(&block)
32
+ ActiveSupport.on_load(:active_record, {}, &block)
20
33
  end
21
34
  end
22
35
  end
@@ -4,16 +4,12 @@ module Doorkeeper
4
4
  def doorkeeper_authorize!(*scopes)
5
5
  @_doorkeeper_scopes = scopes.presence || Doorkeeper.configuration.default_scopes
6
6
 
7
- unless valid_doorkeeper_token?
8
- doorkeeper_render_error
9
- end
7
+ doorkeeper_render_error unless valid_doorkeeper_token?
10
8
  end
11
9
 
12
- def doorkeeper_unauthorized_render_options(error: nil)
13
- end
10
+ def doorkeeper_unauthorized_render_options(**); end
14
11
 
15
- def doorkeeper_forbidden_render_options(error: nil)
16
- end
12
+ def doorkeeper_forbidden_render_options(**); end
17
13
 
18
14
  def valid_doorkeeper_token?
19
15
  doorkeeper_token && doorkeeper_token.acceptable?(@_doorkeeper_scopes)
@@ -23,14 +19,15 @@ module Doorkeeper
23
19
 
24
20
  def doorkeeper_render_error
25
21
  error = doorkeeper_error
26
- headers.merge! error.headers.reject { |k| "Content-Type" == k }
22
+ headers.merge!(error.headers.reject { |k| k == "Content-Type" })
27
23
  doorkeeper_render_error_with(error)
28
24
  end
29
25
 
30
26
  def doorkeeper_render_error_with(error)
31
27
  options = doorkeeper_render_options(error) || {}
32
28
  status = doorkeeper_status_for_error(
33
- error, options.delete(:respond_not_found_when_forbidden))
29
+ error, options.delete(:respond_not_found_when_forbidden)
30
+ )
34
31
  if options.blank?
35
32
  head status
36
33
  else
@@ -69,7 +66,7 @@ module Doorkeeper
69
66
  end
70
67
 
71
68
  def doorkeeper_token
72
- @_doorkeeper_token ||= OAuth::Token.authenticate(
69
+ @doorkeeper_token ||= OAuth::Token.authenticate(
73
70
  request,
74
71
  *Doorkeeper.configuration.access_token_methods
75
72
  )
@@ -4,8 +4,11 @@ require 'doorkeeper/rails/routes/mapper'
4
4
  module Doorkeeper
5
5
  module Rails
6
6
  class Routes # :nodoc:
7
+ mattr_reader :mapping do
8
+ {}
9
+ end
10
+
7
11
  module Helper
8
- # TODO: options hash is not being used
9
12
  def use_doorkeeper(options = {}, &block)
10
13
  Doorkeeper::Rails::Routes.new(self, &block).generate_routes!(options)
11
14
  end
@@ -20,6 +23,10 @@ module Doorkeeper
20
23
  def initialize(routes, &block)
21
24
  @routes = routes
22
25
  @mapping = Mapper.new.map(&block)
26
+
27
+ if Doorkeeper.configuration.api_only
28
+ @mapping.skips.push(:applications, :authorized_applications)
29
+ end
23
30
  end
24
31
 
25
32
  def generate_routes!(options)
@@ -27,6 +34,7 @@ module Doorkeeper
27
34
  map_route(:authorizations, :authorization_routes)
28
35
  map_route(:tokens, :token_routes)
29
36
  map_route(:tokens, :revoke_routes)
37
+ map_route(:tokens, :introspect_routes)
30
38
  map_route(:applications, :application_routes)
31
39
  map_route(:authorized_applications, :authorized_applications_routes)
32
40
  map_route(:token_info, :token_info_routes)
@@ -36,20 +44,22 @@ module Doorkeeper
36
44
  private
37
45
 
38
46
  def map_route(name, method)
39
- unless @mapping.skipped?(name)
40
- send method, @mapping[name]
41
- end
47
+ return if @mapping.skipped?(name)
48
+
49
+ send(method, @mapping[name])
50
+
51
+ mapping[name] = @mapping[name]
42
52
  end
43
53
 
44
54
  def authorization_routes(mapping)
45
55
  routes.resource(
46
56
  :authorization,
47
57
  path: 'authorize',
48
- only: [:create, :destroy],
58
+ only: %i[create destroy],
49
59
  as: mapping[:as],
50
60
  controller: mapping[:controllers]
51
61
  ) do
52
- routes.get '/:code', action: :show, on: :member
62
+ routes.get '/native', action: :show, on: :member
53
63
  routes.get '/', action: :new, on: :member
54
64
  end
55
65
  end
@@ -67,6 +77,10 @@ module Doorkeeper
67
77
  routes.post 'revoke', controller: mapping[:controllers], action: :revoke
68
78
  end
69
79
 
80
+ def introspect_routes(mapping)
81
+ routes.post 'introspect', controller: mapping[:controllers], action: :introspect
82
+ end
83
+
70
84
  def token_info_routes(mapping)
71
85
  routes.resource(
72
86
  :token_info,
@@ -81,7 +95,7 @@ module Doorkeeper
81
95
  end
82
96
 
83
97
  def authorized_applications_routes(mapping)
84
- routes.resources :authorized_applications, only: [:index, :destroy], controller: mapping[:controllers]
98
+ routes.resources :authorized_applications, only: %i[index destroy], controller: mapping[:controllers]
85
99
  end
86
100
  end
87
101
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :doorkeeper do
4
+ namespace :db do
5
+ desc 'Removes stale data from doorkeeper related database tables'
6
+ task cleanup: [
7
+ 'doorkeeper:db:cleanup:revoked_tokens',
8
+ 'doorkeeper:db:cleanup:expired_tokens',
9
+ 'doorkeeper:db:cleanup:revoked_grants',
10
+ 'doorkeeper:db:cleanup:expired_grants'
11
+ ]
12
+
13
+ namespace :cleanup do
14
+ desc 'Removes stale access tokens'
15
+ task revoked_tokens: 'doorkeeper:setup' do
16
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessToken)
17
+ cleaner.clean_revoked
18
+ end
19
+
20
+ desc 'Removes expired (TTL passed) access tokens'
21
+ task expired_tokens: 'doorkeeper:setup' do
22
+ expirable_tokens = Doorkeeper::AccessToken.where(refresh_token: nil)
23
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(expirable_tokens)
24
+ cleaner.clean_expired(Doorkeeper.configuration.access_token_expires_in)
25
+ end
26
+
27
+ desc 'Removes stale access grants'
28
+ task revoked_grants: 'doorkeeper:setup' do
29
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
30
+ cleaner.clean_revoked
31
+ end
32
+
33
+ desc 'Removes expired (TTL passed) access grants'
34
+ task expired_grants: 'doorkeeper:setup' do
35
+ cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
36
+ cleaner.clean_expired(Doorkeeper.configuration.authorization_code_expires_in)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :doorkeeper do
4
+ task setup: :environment do
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Rake
5
+ class << self
6
+ def load_tasks
7
+ glob = File.join(File.absolute_path(__dir__), 'rake', '*.rake')
8
+ Dir[glob].each do |rake_file|
9
+ load rake_file
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class AuthorizationCode < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class ClientCredentials < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class Code < Strategy
@@ -1,9 +1,7 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class Password < Strategy
6
- delegate :credentials, :resource_owner, :parameters, to: :server
4
+ delegate :credentials, :resource_owner, :parameters, :client, to: :server
7
5
 
8
6
  def request
9
7
  @request ||= OAuth::PasswordAccessTokenRequest.new(
@@ -13,16 +11,6 @@ module Doorkeeper
13
11
  parameters
14
12
  )
15
13
  end
16
-
17
- private
18
-
19
- def client
20
- if credentials
21
- server.client
22
- elsif parameters[:client_id]
23
- server.client_via_uid
24
- end
25
- end
26
14
  end
27
15
  end
28
16
  end
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class RefreshToken < Strategy
@@ -1,5 +1,3 @@
1
- require 'doorkeeper/request/strategy'
2
-
3
1
  module Doorkeeper
4
2
  module Request
5
3
  class Token < Strategy
@@ -1,40 +1,39 @@
1
- require 'doorkeeper/request/authorization_code'
2
- require 'doorkeeper/request/client_credentials'
3
- require 'doorkeeper/request/code'
4
- require 'doorkeeper/request/password'
5
- require 'doorkeeper/request/refresh_token'
6
- require 'doorkeeper/request/token'
7
-
8
1
  module Doorkeeper
9
2
  module Request
10
- module_function
3
+ class << self
4
+ def authorization_strategy(response_type)
5
+ get_strategy(response_type, authorization_response_types)
6
+ rescue NameError
7
+ raise Errors::InvalidAuthorizationStrategy
8
+ end
11
9
 
12
- def authorization_strategy(response_type)
13
- get_strategy response_type, authorization_response_types
14
- rescue NameError
15
- raise Errors::InvalidAuthorizationStrategy
16
- end
10
+ def token_strategy(grant_type)
11
+ get_strategy(grant_type, token_grant_types)
12
+ rescue NameError
13
+ raise Errors::InvalidTokenStrategy
14
+ end
17
15
 
18
- def token_strategy(grant_type)
19
- get_strategy grant_type, token_grant_types
20
- rescue NameError
21
- raise Errors::InvalidTokenStrategy
22
- end
16
+ def get_strategy(grant_or_request_type, available)
17
+ raise Errors::MissingRequestStrategy if grant_or_request_type.blank?
18
+ raise NameError unless available.include?(grant_or_request_type.to_s)
23
19
 
24
- def get_strategy(grant_or_request_type, available)
25
- fail Errors::MissingRequestStrategy unless grant_or_request_type.present?
26
- fail NameError unless available.include?(grant_or_request_type.to_s)
27
- "Doorkeeper::Request::#{grant_or_request_type.to_s.camelize}".constantize
28
- end
20
+ build_strategy_class(grant_or_request_type)
21
+ end
29
22
 
30
- def authorization_response_types
31
- Doorkeeper.configuration.authorization_response_types
32
- end
33
- private_class_method :authorization_response_types
23
+ private
24
+
25
+ def authorization_response_types
26
+ Doorkeeper.configuration.authorization_response_types
27
+ end
28
+
29
+ def token_grant_types
30
+ Doorkeeper.configuration.token_grant_types
31
+ end
34
32
 
35
- def token_grant_types
36
- Doorkeeper.configuration.token_grant_types
33
+ def build_strategy_class(grant_or_request_type)
34
+ strategy_class_name = grant_or_request_type.to_s.tr(' ', '_').camelize
35
+ "Doorkeeper::Request::#{strategy_class_name}".constantize
36
+ end
37
37
  end
38
- private_class_method :token_grant_types
39
38
  end
40
39
  end
@@ -6,9 +6,10 @@ module Doorkeeper
6
6
 
7
7
  def validate
8
8
  @error = nil
9
+
9
10
  self.class.validations.each do |validation|
11
+ @error = validation[:options][:error] unless send("validate_#{validation[:attribute]}")
10
12
  break if @error
11
- @error = validation.last unless send("validate_#{validation.first}")
12
13
  end
13
14
  end
14
15
 
@@ -19,7 +20,7 @@ module Doorkeeper
19
20
 
20
21
  module ClassMethods
21
22
  def validate(attribute, options = {})
22
- validations << [attribute, options[:error]]
23
+ validations << { attribute: attribute, options: options }
23
24
  end
24
25
 
25
26
  def validations
@@ -1,3 +1,16 @@
1
1
  module Doorkeeper
2
- VERSION = "4.2.5".freeze
2
+ def self.gem_version
3
+ Gem::Version.new VERSION::STRING
4
+ end
5
+
6
+ module VERSION
7
+ # Semantic versioning
8
+ MAJOR = 5
9
+ MINOR = 0
10
+ TINY = 0
11
+ PRE = nil
12
+
13
+ # Full version number
14
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
15
+ end
3
16
  end