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.
- checksums.yaml +7 -0
- data/doorkeeper-5.9.3/CHANGELOG.md +1208 -0
- data/doorkeeper-5.9.3/MIT-LICENSE +20 -0
- data/doorkeeper-5.9.3/README.md +186 -0
- data/doorkeeper-5.9.3/app/assets/stylesheets/doorkeeper/admin/application.css +10 -0
- data/doorkeeper-5.9.3/app/assets/stylesheets/doorkeeper/application.css +64 -0
- data/doorkeeper-5.9.3/app/controllers/doorkeeper/application_controller.rb +14 -0
- data/doorkeeper-5.9.3/app/controllers/doorkeeper/application_metal_controller.rb +13 -0
- data/doorkeeper-5.9.3/app/controllers/doorkeeper/applications_controller.rb +99 -0
- data/doorkeeper-5.9.3/app/controllers/doorkeeper/authorizations_controller.rb +164 -0
- data/doorkeeper-5.9.3/app/controllers/doorkeeper/authorized_applications_controller.rb +33 -0
- data/doorkeeper-5.9.3/app/controllers/doorkeeper/token_info_controller.rb +25 -0
- data/doorkeeper-5.9.3/app/controllers/doorkeeper/tokens_controller.rb +180 -0
- data/doorkeeper-5.9.3/app/helpers/doorkeeper/dashboard_helper.rb +21 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/applications/_delete_form.html.erb +6 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/applications/_form.html.erb +59 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/applications/edit.html.erb +5 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/applications/index.html.erb +38 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/applications/new.html.erb +5 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/applications/show.html.erb +63 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/error.html.erb +9 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/new.html.erb +46 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/show.html.erb +7 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +4 -0
- data/doorkeeper-5.9.3/app/views/doorkeeper/authorized_applications/index.html.erb +24 -0
- data/doorkeeper-5.9.3/app/views/layouts/doorkeeper/admin.html.erb +39 -0
- data/doorkeeper-5.9.3/app/views/layouts/doorkeeper/application.html.erb +23 -0
- data/doorkeeper-5.9.3/config/locales/en.yml +155 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/config/option.rb +82 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/config/validations.rb +65 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/config.rb +721 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/engine.rb +38 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/errors.rb +85 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/flow.rb +44 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/registry.rb +50 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow.rb +45 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/grape/authorization_decorator.rb +19 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/grape/helpers.rb +58 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/helpers/controller.rb +91 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/access_grant_mixin.rb +124 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/access_token_mixin.rb +526 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/application_mixin.rb +96 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/accessible.rb +15 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/expirable.rb +36 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +96 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/orderable.rb +15 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/ownership.rb +18 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +29 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/revocable.rb +31 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/scopes.rb +27 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/write_to_primary.rb +57 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/code.rb +76 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/context.rb +17 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/token.rb +100 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/uri_builder.rb +33 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization_code_request.rb +125 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/base_request.rb +68 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/base_response.rb +31 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client/credentials.rb +34 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client.rb +28 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/creator.rb +57 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/issuer.rb +48 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/validator.rb +55 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/code_request.rb +25 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/code_response.rb +51 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/error.rb +16 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/error_response.rb +121 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/forbidden_token_response.rb +31 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/scope_checker.rb +50 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/unique_token.rb +30 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/uri_checker.rb +83 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/hooks/context.rb +21 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/invalid_request_response.rb +47 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/invalid_token_response.rb +54 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/password_access_token_request.rb +75 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/pre_authorization.rb +187 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/refresh_token_request.rb +144 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/scopes.rb +134 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token.rb +66 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_introspection.rb +220 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_request.rb +25 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_response.rb +38 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/oauth.rb +13 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/access_grant.rb +9 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/access_token.rb +9 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/application.rb +10 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +64 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/access_token.rb +95 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/application.rb +223 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +44 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record.rb +41 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rails/helpers.rb +82 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/mapper.rb +30 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/mapping.rb +40 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes.rb +110 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rake/db.rake +40 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rake/setup.rake +6 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/rake.rb +14 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request/authorization_code.rb +26 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request/client_credentials.rb +17 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request/code.rb +17 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request/password.rb +19 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request/refresh_token.rb +22 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request/strategy.rb +19 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request/token.rb +17 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/request.rb +73 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/revocable_tokens/revocable_access_token.rb +21 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/revocable_tokens/revocable_refresh_token.rb +21 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/base.rb +64 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/server.rb +44 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/stale_records_cleaner.rb +24 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/validations.rb +33 -0
- data/doorkeeper-5.9.3/lib/doorkeeper/version.rb +14 -0
- data/doorkeeper-5.9.3/lib/doorkeeper.rb +209 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/application_owner_generator.rb +33 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/install_generator.rb +22 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/migration_generator.rb +32 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/pkce_generator.rb +33 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/previous_refresh_token_generator.rb +41 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/remove_applications_secret_not_null_constraint_generator.rb +33 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/README +24 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +13 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/initializer.rb +544 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/migration.rb.erb +99 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/remove_applications_secret_not_null_constraint.rb.erb +7 -0
- data/doorkeeper-5.9.3/lib/generators/doorkeeper/views_generator.rb +18 -0
- data/doorkeeper-5.9.3/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +6 -0
- data/super-smart-kit.gemspec +12 -0
- 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
|