super-smart-kit 0.0.1

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 (149) hide show
  1. checksums.yaml +7 -0
  2. data/doorkeeper-5.9.3/CHANGELOG.md +1208 -0
  3. data/doorkeeper-5.9.3/MIT-LICENSE +20 -0
  4. data/doorkeeper-5.9.3/README.md +186 -0
  5. data/doorkeeper-5.9.3/app/assets/stylesheets/doorkeeper/admin/application.css +10 -0
  6. data/doorkeeper-5.9.3/app/assets/stylesheets/doorkeeper/application.css +64 -0
  7. data/doorkeeper-5.9.3/app/controllers/doorkeeper/application_controller.rb +14 -0
  8. data/doorkeeper-5.9.3/app/controllers/doorkeeper/application_metal_controller.rb +13 -0
  9. data/doorkeeper-5.9.3/app/controllers/doorkeeper/applications_controller.rb +99 -0
  10. data/doorkeeper-5.9.3/app/controllers/doorkeeper/authorizations_controller.rb +164 -0
  11. data/doorkeeper-5.9.3/app/controllers/doorkeeper/authorized_applications_controller.rb +33 -0
  12. data/doorkeeper-5.9.3/app/controllers/doorkeeper/token_info_controller.rb +25 -0
  13. data/doorkeeper-5.9.3/app/controllers/doorkeeper/tokens_controller.rb +180 -0
  14. data/doorkeeper-5.9.3/app/helpers/doorkeeper/dashboard_helper.rb +21 -0
  15. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/_delete_form.html.erb +6 -0
  16. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/_form.html.erb +59 -0
  17. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/edit.html.erb +5 -0
  18. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/index.html.erb +38 -0
  19. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/new.html.erb +5 -0
  20. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/show.html.erb +63 -0
  21. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/error.html.erb +9 -0
  22. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  23. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/new.html.erb +46 -0
  24. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/show.html.erb +7 -0
  25. data/doorkeeper-5.9.3/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +4 -0
  26. data/doorkeeper-5.9.3/app/views/doorkeeper/authorized_applications/index.html.erb +24 -0
  27. data/doorkeeper-5.9.3/app/views/layouts/doorkeeper/admin.html.erb +39 -0
  28. data/doorkeeper-5.9.3/app/views/layouts/doorkeeper/application.html.erb +23 -0
  29. data/doorkeeper-5.9.3/config/locales/en.yml +155 -0
  30. data/doorkeeper-5.9.3/lib/doorkeeper/config/abstract_builder.rb +28 -0
  31. data/doorkeeper-5.9.3/lib/doorkeeper/config/option.rb +82 -0
  32. data/doorkeeper-5.9.3/lib/doorkeeper/config/validations.rb +65 -0
  33. data/doorkeeper-5.9.3/lib/doorkeeper/config.rb +721 -0
  34. data/doorkeeper-5.9.3/lib/doorkeeper/engine.rb +38 -0
  35. data/doorkeeper-5.9.3/lib/doorkeeper/errors.rb +85 -0
  36. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  37. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/flow.rb +44 -0
  38. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/registry.rb +50 -0
  39. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow.rb +45 -0
  40. data/doorkeeper-5.9.3/lib/doorkeeper/grape/authorization_decorator.rb +19 -0
  41. data/doorkeeper-5.9.3/lib/doorkeeper/grape/helpers.rb +58 -0
  42. data/doorkeeper-5.9.3/lib/doorkeeper/helpers/controller.rb +91 -0
  43. data/doorkeeper-5.9.3/lib/doorkeeper/models/access_grant_mixin.rb +124 -0
  44. data/doorkeeper-5.9.3/lib/doorkeeper/models/access_token_mixin.rb +526 -0
  45. data/doorkeeper-5.9.3/lib/doorkeeper/models/application_mixin.rb +96 -0
  46. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/accessible.rb +15 -0
  47. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/expirable.rb +36 -0
  48. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +96 -0
  49. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/orderable.rb +15 -0
  50. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/ownership.rb +18 -0
  51. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +29 -0
  52. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  53. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  54. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/revocable.rb +31 -0
  55. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/scopes.rb +27 -0
  56. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  57. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/write_to_primary.rb +57 -0
  58. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/code.rb +76 -0
  59. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  60. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/token.rb +100 -0
  61. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/uri_builder.rb +33 -0
  62. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization_code_request.rb +125 -0
  63. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/base_request.rb +68 -0
  64. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/base_response.rb +31 -0
  65. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client/credentials.rb +34 -0
  66. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client.rb +28 -0
  67. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/creator.rb +57 -0
  68. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/issuer.rb +48 -0
  69. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/validator.rb +55 -0
  70. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
  71. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/code_request.rb +25 -0
  72. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/code_response.rb +51 -0
  73. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/error.rb +16 -0
  74. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/error_response.rb +121 -0
  75. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/forbidden_token_response.rb +31 -0
  76. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/scope_checker.rb +50 -0
  77. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/unique_token.rb +30 -0
  78. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/uri_checker.rb +83 -0
  79. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  80. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/invalid_request_response.rb +47 -0
  81. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/invalid_token_response.rb +54 -0
  82. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  83. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/password_access_token_request.rb +75 -0
  84. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/pre_authorization.rb +187 -0
  85. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/refresh_token_request.rb +144 -0
  86. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/scopes.rb +134 -0
  87. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token.rb +66 -0
  88. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_introspection.rb +220 -0
  89. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_request.rb +25 -0
  90. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_response.rb +38 -0
  91. data/doorkeeper-5.9.3/lib/doorkeeper/oauth.rb +13 -0
  92. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/access_grant.rb +9 -0
  93. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/access_token.rb +9 -0
  94. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/application.rb +10 -0
  95. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +64 -0
  96. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/access_token.rb +95 -0
  97. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/application.rb +223 -0
  98. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  99. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +44 -0
  100. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record.rb +41 -0
  101. data/doorkeeper-5.9.3/lib/doorkeeper/rails/helpers.rb +82 -0
  102. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  103. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/mapper.rb +30 -0
  104. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/mapping.rb +40 -0
  105. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/registry.rb +45 -0
  106. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes.rb +110 -0
  107. data/doorkeeper-5.9.3/lib/doorkeeper/rake/db.rake +40 -0
  108. data/doorkeeper-5.9.3/lib/doorkeeper/rake/setup.rake +6 -0
  109. data/doorkeeper-5.9.3/lib/doorkeeper/rake.rb +14 -0
  110. data/doorkeeper-5.9.3/lib/doorkeeper/request/authorization_code.rb +26 -0
  111. data/doorkeeper-5.9.3/lib/doorkeeper/request/client_credentials.rb +17 -0
  112. data/doorkeeper-5.9.3/lib/doorkeeper/request/code.rb +17 -0
  113. data/doorkeeper-5.9.3/lib/doorkeeper/request/password.rb +19 -0
  114. data/doorkeeper-5.9.3/lib/doorkeeper/request/refresh_token.rb +22 -0
  115. data/doorkeeper-5.9.3/lib/doorkeeper/request/strategy.rb +19 -0
  116. data/doorkeeper-5.9.3/lib/doorkeeper/request/token.rb +17 -0
  117. data/doorkeeper-5.9.3/lib/doorkeeper/request.rb +73 -0
  118. data/doorkeeper-5.9.3/lib/doorkeeper/revocable_tokens/revocable_access_token.rb +21 -0
  119. data/doorkeeper-5.9.3/lib/doorkeeper/revocable_tokens/revocable_refresh_token.rb +21 -0
  120. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/base.rb +64 -0
  121. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  122. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/plain.rb +33 -0
  123. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  124. data/doorkeeper-5.9.3/lib/doorkeeper/server.rb +44 -0
  125. data/doorkeeper-5.9.3/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  126. data/doorkeeper-5.9.3/lib/doorkeeper/validations.rb +33 -0
  127. data/doorkeeper-5.9.3/lib/doorkeeper/version.rb +14 -0
  128. data/doorkeeper-5.9.3/lib/doorkeeper.rb +209 -0
  129. data/doorkeeper-5.9.3/lib/generators/doorkeeper/application_owner_generator.rb +33 -0
  130. data/doorkeeper-5.9.3/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  131. data/doorkeeper-5.9.3/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  132. data/doorkeeper-5.9.3/lib/generators/doorkeeper/install_generator.rb +22 -0
  133. data/doorkeeper-5.9.3/lib/generators/doorkeeper/migration_generator.rb +32 -0
  134. data/doorkeeper-5.9.3/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  135. data/doorkeeper-5.9.3/lib/generators/doorkeeper/previous_refresh_token_generator.rb +41 -0
  136. data/doorkeeper-5.9.3/lib/generators/doorkeeper/remove_applications_secret_not_null_constraint_generator.rb +33 -0
  137. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/README +24 -0
  138. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  139. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
  140. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +13 -0
  141. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  142. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  143. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/initializer.rb +544 -0
  144. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/migration.rb.erb +99 -0
  145. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/remove_applications_secret_not_null_constraint.rb.erb +7 -0
  146. data/doorkeeper-5.9.3/lib/generators/doorkeeper/views_generator.rb +18 -0
  147. data/doorkeeper-5.9.3/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +6 -0
  148. data/super-smart-kit.gemspec +12 -0
  149. metadata +188 -0
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module ExpirationTimeSqlMath
6
+ extend ::ActiveSupport::Concern
7
+
8
+ WARNING_MESSAGE = <<~WARNING.squish
9
+ [DOORKEEPER] Doorkeeper doesn't support expiration time math for your database adapter.
10
+ Records with an individual expires_in value longer than the global TTL may be incorrectly processed.
11
+ Please add a class method `custom_expiration_time_sql` to your AccessToken/AccessGrant models/mixins to provide a custom
12
+ SQL expression to calculate access token expiration time. See lib/doorkeeper/orm/active_record/mixins/access_token.rb
13
+ for more details.
14
+ WARNING
15
+
16
+ class ExpirationTimeSqlGenerator
17
+ attr_reader :model
18
+
19
+ delegate :table_name, to: :@model
20
+
21
+ def initialize(model)
22
+ @model = model
23
+ end
24
+
25
+ def generate_sql
26
+ raise "`generate_sql` should be overridden for a #{self.class.name}!"
27
+ end
28
+ end
29
+
30
+ class MySqlExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
31
+ def generate_sql
32
+ Arel.sql("DATE_ADD(#{table_name}.created_at, INTERVAL #{table_name}.expires_in SECOND)")
33
+ end
34
+ end
35
+
36
+ class SqlLiteExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
37
+ def generate_sql
38
+ Arel.sql("DATETIME(#{table_name}.created_at, '+' || #{table_name}.expires_in || ' SECONDS')")
39
+ end
40
+ end
41
+
42
+ class SqlServerExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
43
+ def generate_sql
44
+ Arel.sql("DATEADD(second, #{table_name}.expires_in, #{table_name}.created_at) AT TIME ZONE 'UTC'")
45
+ end
46
+ end
47
+
48
+ class OracleExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
49
+ def generate_sql
50
+ Arel.sql("#{table_name}.created_at + INTERVAL to_char(#{table_name}.expires_in) second")
51
+ end
52
+ end
53
+
54
+ class PostgresExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
55
+ def generate_sql
56
+ Arel.sql("#{table_name}.created_at + #{table_name}.expires_in * INTERVAL '1 SECOND'")
57
+ end
58
+ end
59
+
60
+ ADAPTERS_MAPPING = {
61
+ "sqlite" => SqlLiteExpirationTimeSqlGenerator,
62
+ "sqlite3" => SqlLiteExpirationTimeSqlGenerator,
63
+ "postgis" => PostgresExpirationTimeSqlGenerator,
64
+ "postgresql" => PostgresExpirationTimeSqlGenerator,
65
+ "mysql" => MySqlExpirationTimeSqlGenerator,
66
+ "mysql2" => MySqlExpirationTimeSqlGenerator,
67
+ "trilogy" => MySqlExpirationTimeSqlGenerator,
68
+ "sqlserver" => SqlServerExpirationTimeSqlGenerator,
69
+ "oracleenhanced" => OracleExpirationTimeSqlGenerator,
70
+ }.freeze
71
+
72
+ module ClassMethods
73
+ def supports_expiration_time_math?
74
+ ADAPTERS_MAPPING.key?(adapter_name.downcase) ||
75
+ respond_to?(:custom_expiration_time_sql)
76
+ end
77
+
78
+ def expiration_time_sql
79
+ if respond_to?(:custom_expiration_time_sql)
80
+ custom_expiration_time_sql
81
+ else
82
+ expiration_time_sql_expression
83
+ end
84
+ end
85
+
86
+ def expiration_time_sql_expression
87
+ ADAPTERS_MAPPING.fetch(adapter_name.downcase).new(self).generate_sql
88
+ end
89
+
90
+ def adapter_name
91
+ ActiveRecord::Base.connection.adapter_name
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Orderable
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def ordered_by(attribute, direction = :asc)
10
+ order(attribute => direction)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Ownership
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ belongs_to :owner, polymorphic: true, optional: true
10
+ validates :owner, presence: true, if: :validate_owner?
11
+ end
12
+
13
+ def validate_owner?
14
+ Doorkeeper.config.confirm_application_owner?
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module PolymorphicResourceOwner
6
+ module ForAccessGrant
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ if Doorkeeper.config.polymorphic_resource_owner?
11
+ belongs_to :resource_owner, polymorphic: true, optional: false
12
+ else
13
+ validates :resource_owner_id, presence: true
14
+ end
15
+ end
16
+ end
17
+
18
+ module ForAccessToken
19
+ extend ActiveSupport::Concern
20
+
21
+ included do
22
+ if Doorkeeper.config.polymorphic_resource_owner?
23
+ belongs_to :resource_owner, polymorphic: true, optional: true
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module ResourceOwnerable
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ # Searches for record by Resource Owner considering Doorkeeper
10
+ # configuration for resource owner association.
11
+ #
12
+ # @param resource_owner [ActiveRecord::Base, Integer]
13
+ # resource owner
14
+ #
15
+ # @return [Doorkeeper::AccessGrant, Doorkeeper::AccessToken]
16
+ # collection of records
17
+ #
18
+ def by_resource_owner(resource_owner)
19
+ if Doorkeeper.configuration.polymorphic_resource_owner?
20
+ where(resource_owner: resource_owner)
21
+ else
22
+ where(resource_owner_id: resource_owner_id_for(resource_owner))
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ # Backward compatible way to retrieve resource owner itself (if
29
+ # polymorphic association enabled) or just it's ID.
30
+ #
31
+ # @param resource_owner [ActiveRecord::Base, Integer]
32
+ # resource owner
33
+ #
34
+ # @return [ActiveRecord::Base, Integer]
35
+ # instance of Resource Owner or it's ID
36
+ #
37
+ def resource_owner_id_for(resource_owner)
38
+ if resource_owner.respond_to?(:to_key)
39
+ resource_owner.id
40
+ else
41
+ resource_owner
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Reusable
6
+ # Indicates whether the object is reusable (i.e. It is not expired and
7
+ # has not crossed reuse_limit).
8
+ #
9
+ # @return [Boolean] true if can be reused and false in other case
10
+ def reusable?
11
+ return false if expired?
12
+ return true unless expires_in
13
+
14
+ threshold_limit = 100 - Doorkeeper.config.token_reuse_limit
15
+ expires_in_seconds >= threshold_limit * expires_in / 100
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Revocable
6
+ # Revokes the object (updates `:revoked_at` attribute setting its value
7
+ # to the specific time).
8
+ #
9
+ # @param clock [Time] time object
10
+ #
11
+ def revoke(clock = Time)
12
+ return if revoked?
13
+
14
+ # Wrap in with_primary_role if the model class supports it
15
+ if self.class.respond_to?(:with_primary_role)
16
+ self.class.with_primary_role { update_attribute(:revoked_at, clock.now.utc) }
17
+ else
18
+ update_attribute(:revoked_at, clock.now.utc)
19
+ end
20
+ end
21
+
22
+ # Indicates whether the object has been revoked.
23
+ #
24
+ # @return [Boolean] true if revoked, false in other case
25
+ #
26
+ def revoked?
27
+ !!(revoked_at && revoked_at <= Time.now.utc)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Scopes
6
+ def scopes
7
+ OAuth::Scopes.from_string(scopes_string)
8
+ end
9
+
10
+ def scopes=(value)
11
+ if value.is_a?(Array)
12
+ super(Doorkeeper::OAuth::Scopes.from_array(value).to_s)
13
+ else
14
+ super(Doorkeeper::OAuth::Scopes.from_string(value.to_s).to_s)
15
+ end
16
+ end
17
+
18
+ def scopes_string
19
+ self[:scopes]
20
+ end
21
+
22
+ def includes_scope?(*required_scopes)
23
+ required_scopes.blank? || required_scopes.any? { |scope| scopes.exists?(scope.to_s) }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ ##
6
+ # Storable finder to provide lookups for input plaintext values which are
7
+ # mapped to their stored versions (e.g., hashing, encryption) before lookup.
8
+ module SecretStorable
9
+ extend ActiveSupport::Concern
10
+
11
+ delegate :secret_strategy,
12
+ :fallback_secret_strategy,
13
+ to: :class
14
+
15
+ # :nodoc
16
+ module ClassMethods
17
+ # Compare the given plaintext with the secret
18
+ #
19
+ # @param input [String]
20
+ # The plain input to compare.
21
+ #
22
+ # @param secret [String]
23
+ # The secret value to compare with.
24
+ #
25
+ # @return [Boolean]
26
+ # Whether input matches secret as per the secret strategy
27
+ #
28
+ delegate :secret_matches?, to: :secret_strategy
29
+
30
+ # Returns an instance of the Doorkeeper::AccessToken with
31
+ # specific token value.
32
+ #
33
+ # @param attr [Symbol]
34
+ # The token attribute we're looking with.
35
+ #
36
+ # @param token [#to_s]
37
+ # token value (any object that responds to `#to_s`)
38
+ #
39
+ # @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
40
+ # if there is no record with such token
41
+ #
42
+ def find_by_plaintext_token(attr, token)
43
+ token = token.to_s
44
+
45
+ find_by(attr => secret_strategy.transform_secret(token)) ||
46
+ find_by_fallback_token(attr, token)
47
+ end
48
+
49
+ # Allow looking up previously plain tokens as a fallback
50
+ # IFF a fallback strategy has been defined
51
+ #
52
+ # @param attr [Symbol]
53
+ # The token attribute we're looking with.
54
+ #
55
+ # @param plain_secret [#to_s]
56
+ # plain secret value (any object that responds to `#to_s`)
57
+ #
58
+ # @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
59
+ # if there is no record with such token
60
+ #
61
+ def find_by_fallback_token(attr, plain_secret)
62
+ return nil unless fallback_secret_strategy
63
+
64
+ # Use the previous strategy to look up
65
+ stored_token = fallback_secret_strategy.transform_secret(plain_secret)
66
+ find_by(attr => stored_token).tap do |resource|
67
+ return nil unless resource
68
+
69
+ upgrade_fallback_value resource, attr, plain_secret
70
+ end
71
+ end
72
+
73
+ # Allow implementations in ORMs to replace a plain
74
+ # value falling back to to avoid it remaining as plain text.
75
+ #
76
+ # @param instance
77
+ # An instance of this model with a plain value token.
78
+ #
79
+ # @param attr
80
+ # The secret attribute name to upgrade.
81
+ #
82
+ # @param plain_secret
83
+ # The plain secret to upgrade.
84
+ #
85
+ def upgrade_fallback_value(instance, attr, plain_secret)
86
+ upgraded = secret_strategy.store_secret(instance, attr, plain_secret)
87
+ instance.update(attr => upgraded)
88
+ end
89
+
90
+ ##
91
+ # Determines the secret storing transformer
92
+ # Unless configured otherwise, uses the plain secret strategy
93
+ def secret_strategy
94
+ ::Doorkeeper::SecretStoring::Plain
95
+ end
96
+
97
+ ##
98
+ # Determine the fallback storing strategy
99
+ # Unless configured, there will be no fallback
100
+ def fallback_secret_strategy
101
+ nil
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module Models
5
+ module Concerns
6
+ # Provides support for Rails read replicas by ensuring write operations
7
+ # use the primary database when automatic role switching is enabled.
8
+ #
9
+ # When Rails uses automatic role switching with read replicas, GET requests
10
+ # are routed to read-only databases. However, Doorkeeper may need to write
11
+ # to the database during GET requests (e.g., creating access tokens during
12
+ # implicit grant flow). This concern wraps write operations with
13
+ # `connected_to(role: :writing)` to ensure they use the primary database.
14
+ #
15
+ # This concern is only active when:
16
+ # 1. ActiveRecord supports `connected_to` (Rails 6.1+)
17
+ # 2. The configuration option is enabled
18
+ #
19
+ module WriteToPrimary
20
+ extend ActiveSupport::Concern
21
+
22
+ class_methods do
23
+ # Executes the given block with a connection to the primary database
24
+ # for writing, if read replica support is enabled and available.
25
+ #
26
+ # @yield Block to execute with write connection
27
+ # @return The result of the block
28
+ #
29
+ def with_primary_role(&block)
30
+ if should_use_primary_role?
31
+ ::ActiveRecord::Base.connected_to(role: :writing, &block)
32
+ else
33
+ yield
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ # Determines if we should explicitly use the primary role for writes
40
+ #
41
+ # @return [Boolean]
42
+ #
43
+ def should_use_primary_role?
44
+ # Guard clause: return false if ActiveRecord is not available
45
+ return false unless defined?(::ActiveRecord::Base)
46
+
47
+ # Only use primary role if:
48
+ # 1. The enable_multiple_database_roles option is enabled in config
49
+ # 2. ActiveRecord supports connected_to (Rails 6.1+)
50
+ Doorkeeper.config.enable_multiple_database_roles &&
51
+ ::ActiveRecord::Base.respond_to?(:connected_to)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module Authorization
6
+ class Code
7
+ attr_reader :pre_auth, :resource_owner, :token
8
+
9
+ def initialize(pre_auth, resource_owner)
10
+ @pre_auth = pre_auth
11
+ @resource_owner = resource_owner
12
+ end
13
+
14
+ def issue_token!
15
+ return @token if defined?(@token)
16
+
17
+ @token = Doorkeeper.config.access_grant_model.with_primary_role do
18
+ Doorkeeper.config.access_grant_model.create!(access_grant_attributes)
19
+ end
20
+ end
21
+
22
+ def oob_redirect
23
+ { action: :show, code: token.plaintext_token }
24
+ end
25
+
26
+ def access_grant?
27
+ true
28
+ end
29
+
30
+ private
31
+
32
+ def authorization_code_expires_in
33
+ Doorkeeper.config.authorization_code_expires_in
34
+ end
35
+
36
+ def access_grant_attributes
37
+ attributes = {
38
+ application_id: pre_auth.client.id,
39
+ expires_in: authorization_code_expires_in,
40
+ redirect_uri: pre_auth.redirect_uri,
41
+ scopes: pre_auth.scopes.to_s,
42
+ }
43
+
44
+ if Doorkeeper.config.polymorphic_resource_owner?
45
+ attributes[:resource_owner] = resource_owner
46
+ else
47
+ attributes[:resource_owner_id] = resource_owner.id
48
+ end
49
+
50
+ pkce_attributes.merge(attributes).merge(custom_attributes)
51
+ end
52
+
53
+ def custom_attributes
54
+ # Custom access token attributes are saved into the access grant,
55
+ # and then included in subsequently generated access tokens.
56
+ @pre_auth.custom_access_token_attributes.to_h.with_indifferent_access
57
+ end
58
+
59
+ def pkce_attributes
60
+ return {} unless pkce_supported?
61
+
62
+ {
63
+ code_challenge: pre_auth.code_challenge,
64
+ code_challenge_method: pre_auth.code_challenge_method,
65
+ }
66
+ end
67
+
68
+ # Ensures firstly, if migration with additional PKCE columns was
69
+ # generated and migrated
70
+ def pkce_supported?
71
+ Doorkeeper.config.access_grant_model.pkce_supported?
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module Authorization
6
+ class Context
7
+ attr_reader :client, :grant_type, :resource_owner, :scopes
8
+
9
+ def initialize(**attributes)
10
+ attributes.each do |name, value|
11
+ instance_variable_set(:"@#{name}", value) if respond_to?(name)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module Authorization
6
+ class Token
7
+ attr_reader :pre_auth, :resource_owner, :token
8
+
9
+ class << self
10
+ def build_context(pre_auth_or_oauth_client, grant_type, scopes, resource_owner)
11
+ oauth_client = if pre_auth_or_oauth_client.respond_to?(:application)
12
+ pre_auth_or_oauth_client.application
13
+ elsif pre_auth_or_oauth_client.respond_to?(:client)
14
+ pre_auth_or_oauth_client.client
15
+ else
16
+ pre_auth_or_oauth_client
17
+ end
18
+
19
+ Doorkeeper::OAuth::Authorization::Context.new(
20
+ client: oauth_client,
21
+ grant_type: grant_type,
22
+ scopes: scopes,
23
+ resource_owner: resource_owner,
24
+ )
25
+ end
26
+
27
+ def access_token_expires_in(configuration, context)
28
+ if configuration.option_defined?(:custom_access_token_expires_in)
29
+ expiration = configuration.custom_access_token_expires_in.call(context)
30
+ return nil if expiration == Float::INFINITY
31
+
32
+ expiration || configuration.access_token_expires_in
33
+ else
34
+ configuration.access_token_expires_in
35
+ end
36
+ end
37
+
38
+ def refresh_token_enabled?(server, context)
39
+ if server.refresh_token_enabled?.respond_to?(:call)
40
+ server.refresh_token_enabled?.call(context)
41
+ else
42
+ !!server.refresh_token_enabled?
43
+ end
44
+ end
45
+ end
46
+
47
+ def initialize(pre_auth, resource_owner)
48
+ @pre_auth = pre_auth
49
+ @resource_owner = resource_owner
50
+ end
51
+
52
+ def issue_token!
53
+ return @token if defined?(@token)
54
+
55
+ context = self.class.build_context(
56
+ pre_auth.client,
57
+ Doorkeeper::OAuth::IMPLICIT,
58
+ pre_auth.scopes,
59
+ resource_owner,
60
+ )
61
+
62
+ @token = Doorkeeper.config.access_token_model.find_or_create_for(
63
+ application: application,
64
+ resource_owner: resource_owner,
65
+ scopes: pre_auth.scopes,
66
+ expires_in: self.class.access_token_expires_in(Doorkeeper.config, context),
67
+ use_refresh_token: false,
68
+ )
69
+ end
70
+
71
+ def application
72
+ return unless pre_auth.client
73
+
74
+ pre_auth.client.is_a?(Doorkeeper.config.application_model) ? pre_auth.client : pre_auth.client.application
75
+ end
76
+
77
+ def oob_redirect
78
+ {
79
+ controller: controller,
80
+ action: :show,
81
+ access_token: token.plaintext_token,
82
+ }
83
+ end
84
+
85
+ def access_token?
86
+ true
87
+ end
88
+
89
+ private
90
+
91
+ def controller
92
+ @controller ||= begin
93
+ mapping = Doorkeeper::Rails::Routes.mapping[:token_info] || {}
94
+ mapping[:controllers] || "doorkeeper/token_info"
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/utils"
4
+
5
+ module Doorkeeper
6
+ module OAuth
7
+ module Authorization
8
+ class URIBuilder
9
+ class << self
10
+ def uri_with_query(url, parameters = {})
11
+ uri = URI.parse(url)
12
+ original_query = Rack::Utils.parse_query(uri.query)
13
+ uri.query = build_query(original_query.merge(parameters))
14
+ uri.to_s
15
+ end
16
+
17
+ def uri_with_fragment(url, parameters = {})
18
+ uri = URI.parse(url)
19
+ uri.fragment = build_query(parameters)
20
+ uri.to_s
21
+ end
22
+
23
+ private
24
+
25
+ def build_query(parameters = {})
26
+ parameters.reject! { |_, value| value.blank? }
27
+ Rack::Utils.build_query(parameters)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end