doorkeeper 5.2.2 → 5.5.4

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 (260) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +198 -3
  3. data/README.md +28 -20
  4. data/app/controllers/doorkeeper/application_controller.rb +3 -2
  5. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
  6. data/app/controllers/doorkeeper/applications_controller.rb +7 -8
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +48 -18
  8. data/app/controllers/doorkeeper/authorized_applications_controller.rb +6 -6
  9. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  10. data/app/controllers/doorkeeper/tokens_controller.rb +70 -25
  11. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  12. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  13. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  14. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  15. data/app/views/doorkeeper/authorizations/new.html.erb +2 -0
  16. data/config/locales/en.yml +9 -2
  17. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  18. data/lib/doorkeeper/config/option.rb +26 -14
  19. data/lib/doorkeeper/config/validations.rb +53 -0
  20. data/lib/doorkeeper/config.rb +214 -122
  21. data/lib/doorkeeper/engine.rb +1 -1
  22. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  23. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  24. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  25. data/lib/doorkeeper/grant_flow.rb +45 -0
  26. data/lib/doorkeeper/grape/helpers.rb +2 -2
  27. data/lib/doorkeeper/helpers/controller.rb +18 -12
  28. data/lib/doorkeeper/models/access_grant_mixin.rb +23 -19
  29. data/lib/doorkeeper/models/access_token_mixin.rb +157 -55
  30. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  31. data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
  32. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  33. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  34. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  35. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  36. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  37. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  38. data/lib/doorkeeper/oauth/authorization/code.rb +22 -9
  39. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  40. data/lib/doorkeeper/oauth/authorization/token.rb +23 -18
  41. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  42. data/lib/doorkeeper/oauth/authorization_code_request.rb +30 -20
  43. data/lib/doorkeeper/oauth/base_request.rb +19 -23
  44. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  45. data/lib/doorkeeper/oauth/client.rb +8 -9
  46. data/lib/doorkeeper/oauth/client_credentials/creator.rb +38 -12
  47. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  48. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +7 -5
  49. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  50. data/lib/doorkeeper/oauth/code_request.rb +4 -4
  51. data/lib/doorkeeper/oauth/code_response.rb +24 -14
  52. data/lib/doorkeeper/oauth/error.rb +1 -1
  53. data/lib/doorkeeper/oauth/error_response.rb +10 -11
  54. data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
  55. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  56. data/lib/doorkeeper/oauth/helpers/unique_token.rb +10 -7
  57. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -19
  58. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  59. data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
  60. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  61. data/lib/doorkeeper/oauth/password_access_token_request.rb +28 -10
  62. data/lib/doorkeeper/oauth/pre_authorization.rb +73 -37
  63. data/lib/doorkeeper/oauth/refresh_token_request.rb +35 -26
  64. data/lib/doorkeeper/oauth/token.rb +6 -7
  65. data/lib/doorkeeper/oauth/token_introspection.rb +12 -16
  66. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  67. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  68. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  69. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  70. data/lib/doorkeeper/orm/active_record/application.rb +5 -95
  71. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
  72. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +60 -0
  73. data/lib/doorkeeper/orm/active_record/mixins/application.rb +199 -0
  74. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +8 -3
  75. data/lib/doorkeeper/orm/active_record.rb +5 -7
  76. data/lib/doorkeeper/rails/helpers.rb +4 -4
  77. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  78. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  79. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  80. data/lib/doorkeeper/rails/routes.rb +17 -25
  81. data/lib/doorkeeper/rake/db.rake +6 -6
  82. data/lib/doorkeeper/rake/setup.rake +5 -0
  83. data/lib/doorkeeper/request/authorization_code.rb +3 -3
  84. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  85. data/lib/doorkeeper/request/password.rb +3 -2
  86. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  87. data/lib/doorkeeper/request/strategy.rb +2 -2
  88. data/lib/doorkeeper/request.rb +49 -12
  89. data/lib/doorkeeper/server.rb +5 -5
  90. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  91. data/lib/doorkeeper/version.rb +2 -6
  92. data/lib/doorkeeper.rb +112 -81
  93. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  94. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  95. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  96. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  97. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  98. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
  99. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  100. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  101. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  102. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +99 -14
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  105. metadata +37 -306
  106. data/Appraisals +0 -40
  107. data/CODE_OF_CONDUCT.md +0 -46
  108. data/CONTRIBUTING.md +0 -49
  109. data/Dangerfile +0 -67
  110. data/Dockerfile +0 -29
  111. data/Gemfile +0 -25
  112. data/NEWS.md +0 -1
  113. data/RELEASING.md +0 -11
  114. data/Rakefile +0 -28
  115. data/SECURITY.md +0 -15
  116. data/UPGRADE.md +0 -2
  117. data/bin/console +0 -16
  118. data/doorkeeper.gemspec +0 -42
  119. data/gemfiles/rails_5_0.gemfile +0 -18
  120. data/gemfiles/rails_5_1.gemfile +0 -18
  121. data/gemfiles/rails_5_2.gemfile +0 -18
  122. data/gemfiles/rails_6_0.gemfile +0 -18
  123. data/gemfiles/rails_master.gemfile +0 -18
  124. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  125. data/spec/controllers/applications_controller_spec.rb +0 -273
  126. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  127. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  128. data/spec/controllers/token_info_controller_spec.rb +0 -50
  129. data/spec/controllers/tokens_controller_spec.rb +0 -498
  130. data/spec/dummy/Rakefile +0 -9
  131. data/spec/dummy/app/assets/config/manifest.js +0 -2
  132. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  133. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  134. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  135. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  136. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  137. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  138. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  139. data/spec/dummy/app/models/user.rb +0 -7
  140. data/spec/dummy/app/views/home/index.html.erb +0 -0
  141. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  142. data/spec/dummy/config/application.rb +0 -49
  143. data/spec/dummy/config/boot.rb +0 -7
  144. data/spec/dummy/config/database.yml +0 -15
  145. data/spec/dummy/config/environment.rb +0 -5
  146. data/spec/dummy/config/environments/development.rb +0 -31
  147. data/spec/dummy/config/environments/production.rb +0 -64
  148. data/spec/dummy/config/environments/test.rb +0 -45
  149. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  150. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  151. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  152. data/spec/dummy/config/initializers/session_store.rb +0 -10
  153. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  154. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  155. data/spec/dummy/config/routes.rb +0 -13
  156. data/spec/dummy/config.ru +0 -6
  157. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  158. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  159. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  160. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  161. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  162. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  163. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  164. data/spec/dummy/db/schema.rb +0 -68
  165. data/spec/dummy/public/404.html +0 -26
  166. data/spec/dummy/public/422.html +0 -26
  167. data/spec/dummy/public/500.html +0 -26
  168. data/spec/dummy/public/favicon.ico +0 -0
  169. data/spec/dummy/script/rails +0 -9
  170. data/spec/factories.rb +0 -30
  171. data/spec/generators/application_owner_generator_spec.rb +0 -28
  172. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  173. data/spec/generators/install_generator_spec.rb +0 -36
  174. data/spec/generators/migration_generator_spec.rb +0 -28
  175. data/spec/generators/pkce_generator_spec.rb +0 -28
  176. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  177. data/spec/generators/templates/routes.rb +0 -4
  178. data/spec/generators/views_generator_spec.rb +0 -29
  179. data/spec/grape/grape_integration_spec.rb +0 -137
  180. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  181. data/spec/lib/config_spec.rb +0 -739
  182. data/spec/lib/doorkeeper_spec.rb +0 -27
  183. data/spec/lib/models/expirable_spec.rb +0 -61
  184. data/spec/lib/models/reusable_spec.rb +0 -40
  185. data/spec/lib/models/revocable_spec.rb +0 -59
  186. data/spec/lib/models/scopes_spec.rb +0 -53
  187. data/spec/lib/models/secret_storable_spec.rb +0 -135
  188. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  189. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -168
  190. data/spec/lib/oauth/base_request_spec.rb +0 -222
  191. data/spec/lib/oauth/base_response_spec.rb +0 -47
  192. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  193. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -97
  194. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  195. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  196. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  197. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  198. data/spec/lib/oauth/client_spec.rb +0 -38
  199. data/spec/lib/oauth/code_request_spec.rb +0 -46
  200. data/spec/lib/oauth/code_response_spec.rb +0 -36
  201. data/spec/lib/oauth/error_response_spec.rb +0 -66
  202. data/spec/lib/oauth/error_spec.rb +0 -23
  203. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  204. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  205. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  206. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  207. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -75
  208. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  209. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  210. data/spec/lib/oauth/pre_authorization_spec.rb +0 -225
  211. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -178
  212. data/spec/lib/oauth/scopes_spec.rb +0 -148
  213. data/spec/lib/oauth/token_request_spec.rb +0 -153
  214. data/spec/lib/oauth/token_response_spec.rb +0 -86
  215. data/spec/lib/oauth/token_spec.rb +0 -158
  216. data/spec/lib/request/strategy_spec.rb +0 -54
  217. data/spec/lib/secret_storing/base_spec.rb +0 -60
  218. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  219. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  220. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  221. data/spec/lib/server_spec.rb +0 -49
  222. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  223. data/spec/models/doorkeeper/access_grant_spec.rb +0 -163
  224. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  225. data/spec/models/doorkeeper/application_spec.rb +0 -377
  226. data/spec/requests/applications/applications_request_spec.rb +0 -259
  227. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  228. data/spec/requests/endpoints/authorization_spec.rb +0 -89
  229. data/spec/requests/endpoints/token_spec.rb +0 -75
  230. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  231. data/spec/requests/flows/authorization_code_spec.rb +0 -513
  232. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  233. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  234. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  235. data/spec/requests/flows/password_spec.rb +0 -296
  236. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  237. data/spec/requests/flows/revoke_token_spec.rb +0 -151
  238. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  239. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  240. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  241. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  242. data/spec/routing/default_routes_spec.rb +0 -41
  243. data/spec/routing/scoped_routes_spec.rb +0 -47
  244. data/spec/spec_helper.rb +0 -57
  245. data/spec/spec_helper_integration.rb +0 -4
  246. data/spec/support/dependencies/factory_bot.rb +0 -4
  247. data/spec/support/doorkeeper_rspec.rb +0 -22
  248. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  249. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  250. data/spec/support/helpers/config_helper.rb +0 -11
  251. data/spec/support/helpers/model_helper.rb +0 -78
  252. data/spec/support/helpers/request_spec_helper.rb +0 -110
  253. data/spec/support/helpers/url_helper.rb +0 -62
  254. data/spec/support/http_method_shim.rb +0 -29
  255. data/spec/support/orm/active_record.rb +0 -5
  256. data/spec/support/shared/controllers_shared_context.rb +0 -123
  257. data/spec/support/shared/hashing_shared_context.rb +0 -36
  258. data/spec/support/shared/models_shared_examples.rb +0 -54
  259. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  260. data/spec/version/version_spec.rb +0 -17
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module Application
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+ self.strict_loading_by_default = false if respond_to?(:strict_loading_by_default)
10
+
11
+ include ::Doorkeeper::ApplicationMixin
12
+
13
+ has_many :access_grants,
14
+ foreign_key: :application_id,
15
+ dependent: :delete_all,
16
+ class_name: Doorkeeper.config.access_grant_class.to_s
17
+
18
+ has_many :access_tokens,
19
+ foreign_key: :application_id,
20
+ dependent: :delete_all,
21
+ class_name: Doorkeeper.config.access_token_class.to_s
22
+
23
+ validates :name, :secret, :uid, presence: true
24
+ validates :uid, uniqueness: { case_sensitive: true }
25
+ validates :redirect_uri, "doorkeeper/redirect_uri": true
26
+ validates :confidential, inclusion: { in: [true, false] }
27
+
28
+ validate :scopes_match_configured, if: :enforce_scopes?
29
+
30
+ before_validation :generate_uid, :generate_secret, on: :create
31
+
32
+ has_many :authorized_tokens,
33
+ -> { where(revoked_at: nil) },
34
+ foreign_key: :application_id,
35
+ class_name: Doorkeeper.config.access_token_class.to_s
36
+
37
+ has_many :authorized_applications,
38
+ through: :authorized_tokens,
39
+ source: :application
40
+
41
+ # Generates a new secret for this application, intended to be used
42
+ # for rotating the secret or in case of compromise.
43
+ #
44
+ # @return [String] new transformed secret value
45
+ #
46
+ def renew_secret
47
+ @raw_secret = Doorkeeper::OAuth::Helpers::UniqueToken.generate
48
+ secret_strategy.store_secret(self, :secret, @raw_secret)
49
+ end
50
+
51
+ # We keep a volatile copy of the raw secret for initial communication
52
+ # The stored refresh_token may be mapped and not available in cleartext.
53
+ #
54
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
55
+ # while hashing strategies do not, so you cannot rely on this value
56
+ # returning a present value for persisted tokens.
57
+ def plaintext_secret
58
+ if secret_strategy.allows_restoring_secrets?
59
+ secret_strategy.restore_secret(self, :secret)
60
+ else
61
+ @raw_secret
62
+ end
63
+ end
64
+
65
+ # Represents client as set of it's attributes in JSON format.
66
+ # This is the right way how we want to override ActiveRecord #to_json.
67
+ #
68
+ # Respects privacy settings and serializes minimum set of attributes
69
+ # for public/private clients and full set for authorized owners.
70
+ #
71
+ # @return [Hash] entity attributes for JSON
72
+ #
73
+ def as_json(options = {})
74
+ # if application belongs to some owner we need to check if it's the same as
75
+ # the one passed in the options or check if we render the client as an owner
76
+ if (respond_to?(:owner) && owner && owner == options[:current_resource_owner]) ||
77
+ options[:as_owner]
78
+ # Owners can see all the client attributes, fallback to ActiveModel serialization
79
+ super
80
+ else
81
+ # if application has no owner or it's owner doesn't match one from the options
82
+ # we render only minimum set of attributes that could be exposed to a public
83
+ only = extract_serializable_attributes(options)
84
+ super(options.merge(only: only))
85
+ end
86
+ end
87
+
88
+ def authorized_for_resource_owner?(resource_owner)
89
+ Doorkeeper.configuration.authorize_resource_owner_for_client.call(self, resource_owner)
90
+ end
91
+
92
+ # We need to hook into this method to allow serializing plan-text secrets
93
+ # when secrets hashing enabled.
94
+ #
95
+ # @param key [String] attribute name
96
+ #
97
+ def read_attribute_for_serialization(key)
98
+ return super unless key.to_s == "secret"
99
+
100
+ plaintext_secret || secret
101
+ end
102
+
103
+ private
104
+
105
+ def generate_uid
106
+ self.uid = Doorkeeper::OAuth::Helpers::UniqueToken.generate if uid.blank?
107
+ end
108
+
109
+ def generate_secret
110
+ return if secret.present?
111
+
112
+ renew_secret
113
+ end
114
+
115
+ def scopes_match_configured
116
+ if scopes.present? && !Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
117
+ scope_str: scopes.to_s,
118
+ server_scopes: Doorkeeper.config.scopes,
119
+ )
120
+ errors.add(:scopes, :not_match_configured)
121
+ end
122
+ end
123
+
124
+ def enforce_scopes?
125
+ Doorkeeper.config.enforce_configured_scopes?
126
+ end
127
+
128
+ # Helper method to extract collection of serializable attribute names
129
+ # considering serialization options (like `only`, `except` and so on).
130
+ #
131
+ # @param options [Hash] serialization options
132
+ #
133
+ # @return [Array<String>]
134
+ # collection of attributes to be serialized using #as_json
135
+ #
136
+ def extract_serializable_attributes(options = {})
137
+ opts = options.try(:dup) || {}
138
+ only = Array.wrap(opts[:only]).map(&:to_s)
139
+
140
+ only = if only.blank?
141
+ client_serializable_attributes
142
+ else
143
+ only & client_serializable_attributes
144
+ end
145
+
146
+ only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
147
+ only.uniq
148
+ end
149
+
150
+ # Collection of attributes that could be serialized for public.
151
+ # Override this method if you need additional attributes to be serialized.
152
+ #
153
+ # @return [Array<String>] collection of serializable attributes
154
+ #
155
+ # NOTE: `serializable_attributes` method already taken by Rails >= 6
156
+ #
157
+ def client_serializable_attributes
158
+ attributes = %w[id name created_at]
159
+ attributes << "uid" unless confidential?
160
+ attributes
161
+ end
162
+ end
163
+
164
+ module ClassMethods
165
+ # Returns Applications associated with active (not revoked) Access Tokens
166
+ # that are owned by the specific Resource Owner.
167
+ #
168
+ # @param resource_owner [ActiveRecord::Base]
169
+ # Resource Owner model instance
170
+ #
171
+ # @return [ActiveRecord::Relation]
172
+ # Applications authorized for the Resource Owner
173
+ #
174
+ def authorized_for(resource_owner)
175
+ resource_access_tokens = Doorkeeper.config.access_token_model.active_for(resource_owner)
176
+ where(id: resource_access_tokens.select(:application_id).distinct)
177
+ end
178
+
179
+ # Revokes AccessToken and AccessGrant records that have not been revoked and
180
+ # associated with the specific Application and Resource Owner.
181
+ #
182
+ # @param resource_owner [ActiveRecord::Base]
183
+ # instance of the Resource Owner model
184
+ #
185
+ def revoke_tokens_and_grants_for(id, resource_owner)
186
+ Doorkeeper.config.access_token_model.revoke_all_for(id, resource_owner)
187
+ Doorkeeper.config.access_grant_model.revoke_all_for(id, resource_owner)
188
+ end
189
+
190
+ private
191
+
192
+ def compute_doorkeeper_table_name
193
+ table_name = "oauth_application"
194
+ table_name = table_name.pluralize if pluralize_table_names
195
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
196
+ end
197
+ end
198
+ end
199
+ end
@@ -8,7 +8,7 @@ module Doorkeeper
8
8
  class RedirectUriValidator < ActiveModel::EachValidator
9
9
  def validate_each(record, attribute, value)
10
10
  if value.blank?
11
- return if Doorkeeper.configuration.allow_blank_redirect_uri?(record)
11
+ return if Doorkeeper.config.allow_blank_redirect_uri?(record)
12
12
 
13
13
  record.errors.add(attribute, :blank)
14
14
  else
@@ -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
@@ -34,7 +35,7 @@ module Doorkeeper
34
35
  end
35
36
 
36
37
  def forbidden_uri?(uri)
37
- Doorkeeper.configuration.forbid_redirect_uri.call(uri)
38
+ Doorkeeper.config.forbid_redirect_uri.call(uri)
38
39
  end
39
40
 
40
41
  def unspecified_scheme?(uri)
@@ -43,12 +44,16 @@ 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
49
54
 
50
55
  def invalid_ssl_uri?(uri)
51
- forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
56
+ forces_ssl = Doorkeeper.config.force_ssl_in_redirect_uri
52
57
  non_https = uri.try(:scheme) == "http"
53
58
 
54
59
  if forces_ssl.respond_to?(:call)
@@ -16,14 +16,12 @@ module Doorkeeper
16
16
  def self.initialize_models!
17
17
  lazy_load do
18
18
  require "doorkeeper/orm/active_record/stale_records_cleaner"
19
- require "doorkeeper/orm/active_record/redirect_uri_validator"
20
19
  require "doorkeeper/orm/active_record/access_grant"
21
20
  require "doorkeeper/orm/active_record/access_token"
22
21
  require "doorkeeper/orm/active_record/application"
23
22
 
24
- if Doorkeeper.configuration.active_record_options[:establish_connection]
23
+ if (options = Doorkeeper.config.active_record_options[:establish_connection])
25
24
  Doorkeeper::Orm::ActiveRecord.models.each do |model|
26
- options = Doorkeeper.configuration.active_record_options[:establish_connection]
27
25
  model.establish_connection(options)
28
26
  end
29
27
  end
@@ -34,7 +32,7 @@ module Doorkeeper
34
32
  lazy_load do
35
33
  require "doorkeeper/models/concerns/ownership"
36
34
 
37
- Doorkeeper::Application.send :include, Doorkeeper::Models::Ownership
35
+ Doorkeeper.config.application_model.include(Doorkeeper::Models::Ownership)
38
36
  end
39
37
  end
40
38
 
@@ -44,9 +42,9 @@ module Doorkeeper
44
42
 
45
43
  def self.models
46
44
  [
47
- Doorkeeper::AccessGrant,
48
- Doorkeeper::AccessToken,
49
- Doorkeeper::Application,
45
+ Doorkeeper.config.access_grant_model,
46
+ Doorkeeper.config.access_token_model,
47
+ Doorkeeper.config.application_model,
50
48
  ]
51
49
  end
52
50
  end
@@ -4,7 +4,7 @@ module Doorkeeper
4
4
  module Rails
5
5
  module Helpers
6
6
  def doorkeeper_authorize!(*scopes)
7
- @_doorkeeper_scopes = scopes.presence || Doorkeeper.configuration.default_scopes
7
+ @_doorkeeper_scopes = scopes.presence || Doorkeeper.config.default_scopes
8
8
 
9
9
  doorkeeper_render_error unless valid_doorkeeper_token?
10
10
  end
@@ -21,7 +21,7 @@ module Doorkeeper
21
21
 
22
22
  def doorkeeper_render_error
23
23
  error = doorkeeper_error
24
- error.raise_exception! if Doorkeeper.configuration.raise_on_errors?
24
+ error.raise_exception! if Doorkeeper.config.raise_on_errors?
25
25
 
26
26
  headers.merge!(error.headers.reject { |k| k == "Content-Type" })
27
27
  doorkeeper_render_error_with(error)
@@ -30,7 +30,7 @@ module Doorkeeper
30
30
  def doorkeeper_render_error_with(error)
31
31
  options = doorkeeper_render_options(error) || {}
32
32
  status = doorkeeper_status_for_error(
33
- error, options.delete(:respond_not_found_when_forbidden)
33
+ error, options.delete(:respond_not_found_when_forbidden),
34
34
  )
35
35
  if options.blank?
36
36
  head status
@@ -72,7 +72,7 @@ module Doorkeeper
72
72
  def doorkeeper_token
73
73
  @doorkeeper_token ||= OAuth::Token.authenticate(
74
74
  request,
75
- *Doorkeeper.configuration.access_token_methods
75
+ *Doorkeeper.config.access_token_methods,
76
76
  )
77
77
  end
78
78
  end
@@ -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
@@ -2,33 +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.send :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
- if Doorkeeper.configuration.api_only
30
- @mapping.skips.push(:applications, :authorized_applications)
31
- end
30
+ def initialize(routes, mapper = Mapper.new, &block)
31
+ super
32
32
  end
33
33
 
34
34
  def generate_routes!(options)
@@ -36,7 +36,7 @@ module Doorkeeper
36
36
  map_route(:authorizations, :authorization_routes)
37
37
  map_route(:tokens, :token_routes)
38
38
  map_route(:tokens, :revoke_routes)
39
- map_route(:tokens, :introspect_routes)
39
+ map_route(:tokens, :introspect_routes) unless Doorkeeper.config.allow_token_introspection.is_a?(FalseClass)
40
40
  map_route(:applications, :application_routes)
41
41
  map_route(:authorized_applications, :authorized_applications_routes)
42
42
  map_route(:token_info, :token_info_routes)
@@ -45,21 +45,13 @@ module Doorkeeper
45
45
 
46
46
  private
47
47
 
48
- def map_route(name, method)
49
- return if @mapping.skipped?(name)
50
-
51
- send(method, @mapping[name])
52
-
53
- mapping[name] = @mapping[name]
54
- end
55
-
56
48
  def authorization_routes(mapping)
57
49
  routes.resource(
58
50
  :authorization,
59
51
  path: "authorize",
60
52
  only: %i[create destroy],
61
53
  as: mapping[:as],
62
- controller: mapping[:controllers]
54
+ controller: mapping[:controllers],
63
55
  ) do
64
56
  routes.get "/native", action: :show, on: :member
65
57
  routes.get "/", action: :new, on: :member
@@ -71,7 +63,7 @@ module Doorkeeper
71
63
  :token,
72
64
  path: "token",
73
65
  only: [:create], as: mapping[:as],
74
- controller: mapping[:controllers]
66
+ controller: mapping[:controllers],
75
67
  )
76
68
  end
77
69
 
@@ -88,7 +80,7 @@ module Doorkeeper
88
80
  :token_info,
89
81
  path: "token/info",
90
82
  only: [:show], as: mapping[:as],
91
- controller: mapping[:controllers]
83
+ controller: mapping[:controllers],
92
84
  )
93
85
  end
94
86
 
@@ -13,27 +13,27 @@ namespace :doorkeeper do
13
13
  namespace :cleanup do
14
14
  desc "Removes stale access tokens"
15
15
  task revoked_tokens: "doorkeeper:setup" do
16
- cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper::AccessToken)
16
+ cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper.config.access_token_model)
17
17
  cleaner.clean_revoked
18
18
  end
19
19
 
20
20
  desc "Removes expired (TTL passed) access tokens"
21
21
  task expired_tokens: "doorkeeper:setup" do
22
- expirable_tokens = Doorkeeper::AccessToken.where(refresh_token: nil)
22
+ expirable_tokens = Doorkeeper.config.access_token_model.where(refresh_token: nil)
23
23
  cleaner = Doorkeeper::StaleRecordsCleaner.new(expirable_tokens)
24
- cleaner.clean_expired(Doorkeeper.configuration.access_token_expires_in)
24
+ cleaner.clean_expired(Doorkeeper.config.access_token_expires_in)
25
25
  end
26
26
 
27
27
  desc "Removes stale access grants"
28
28
  task revoked_grants: "doorkeeper:setup" do
29
- cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
29
+ cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper.config.access_grant_model)
30
30
  cleaner.clean_revoked
31
31
  end
32
32
 
33
33
  desc "Removes expired (TTL passed) access grants"
34
34
  task expired_grants: "doorkeeper:setup" do
35
- cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
36
- cleaner.clean_expired(Doorkeeper.configuration.authorization_code_expires_in)
35
+ cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper.config.access_grant_model)
36
+ cleaner.clean_expired(Doorkeeper.config.authorization_code_expires_in)
37
37
  end
38
38
  end
39
39
  end
@@ -2,5 +2,10 @@
2
2
 
3
3
  namespace :doorkeeper do
4
4
  task setup: :environment do
5
+ # Dirty hack to manually initialize AR because of lazy auto-loading,
6
+ # in other case we'll see NameError: uninitialized constant Doorkeeper::AccessToken
7
+ if Doorkeeper.config.orm == :active_record && defined?(::ActiveRecord::Base)
8
+ Object.const_get("::ActiveRecord::Base")
9
+ end
5
10
  end
6
11
  end
@@ -7,10 +7,10 @@ module Doorkeeper
7
7
 
8
8
  def request
9
9
  @request ||= OAuth::AuthorizationCodeRequest.new(
10
- Doorkeeper.configuration,
10
+ Doorkeeper.config,
11
11
  grant,
12
12
  client,
13
- parameters
13
+ parameters,
14
14
  )
15
15
  end
16
16
 
@@ -19,7 +19,7 @@ module Doorkeeper
19
19
  def grant
20
20
  raise Errors::MissingRequiredParameter, :code if parameters[:code].blank?
21
21
 
22
- AccessGrant.by_token(parameters[:code])
22
+ Doorkeeper.config.access_grant_model.by_token(parameters[:code])
23
23
  end
24
24
  end
25
25
  end
@@ -7,9 +7,9 @@ module Doorkeeper
7
7
 
8
8
  def request
9
9
  @request ||= OAuth::ClientCredentialsRequest.new(
10
- Doorkeeper.configuration,
10
+ Doorkeeper.config,
11
11
  client,
12
- parameters
12
+ parameters,
13
13
  )
14
14
  end
15
15
  end
@@ -7,10 +7,11 @@ module Doorkeeper
7
7
 
8
8
  def request
9
9
  @request ||= OAuth::PasswordAccessTokenRequest.new(
10
- Doorkeeper.configuration,
10
+ Doorkeeper.config,
11
11
  client,
12
+ credentials,
12
13
  resource_owner,
13
- parameters
14
+ parameters,
14
15
  )
15
16
  end
16
17
  end
@@ -6,14 +6,15 @@ module Doorkeeper
6
6
  delegate :credentials, :parameters, to: :server
7
7
 
8
8
  def refresh_token
9
- AccessToken.by_refresh_token(parameters[:refresh_token])
9
+ Doorkeeper.config.access_token_model.by_refresh_token(parameters[:refresh_token])
10
10
  end
11
11
 
12
12
  def request
13
13
  @request ||= OAuth::RefreshTokenRequest.new(
14
- Doorkeeper.configuration,
15
- refresh_token, credentials,
16
- parameters
14
+ Doorkeeper.config,
15
+ refresh_token,
16
+ credentials,
17
+ parameters,
17
18
  )
18
19
  end
19
20
  end
@@ -3,12 +3,12 @@
3
3
  module Doorkeeper
4
4
  module Request
5
5
  class Strategy
6
- attr_accessor :server
6
+ attr_reader :server
7
7
 
8
8
  delegate :authorize, to: :request
9
9
 
10
10
  def initialize(server)
11
- self.server = server
11
+ @server = server
12
12
  end
13
13
 
14
14
  def request