doorkeeper 5.0.3 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +11 -21
- data/Appraisals +29 -7
- data/Dangerfile +5 -2
- data/Gemfile +19 -5
- data/NEWS.md +81 -21
- data/README.md +75 -485
- data/Rakefile +10 -8
- data/app/controllers/doorkeeper/application_controller.rb +1 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -13
- data/app/controllers/doorkeeper/applications_controller.rb +20 -8
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
- data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
- data/app/validators/redirect_uri_validator.rb +5 -2
- data/app/views/doorkeeper/applications/_form.html.erb +6 -0
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +16 -0
- data/config/locales/en.yml +1 -0
- data/doorkeeper.gemspec +24 -21
- data/gemfiles/rails_5_0.gemfile +9 -4
- data/gemfiles/rails_5_1.gemfile +9 -4
- data/gemfiles/rails_5_2.gemfile +10 -5
- data/gemfiles/rails_6_0.gemfile +17 -0
- data/gemfiles/rails_master.gemfile +9 -9
- data/lib/doorkeeper/config/option.rb +64 -0
- data/lib/doorkeeper/config.rb +191 -75
- data/lib/doorkeeper/engine.rb +1 -1
- data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
- data/lib/doorkeeper/grape/helpers.rb +3 -3
- data/lib/doorkeeper/helpers/controller.rb +3 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
- data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
- data/lib/doorkeeper/models/application_mixin.rb +43 -1
- data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +10 -6
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
- data/lib/doorkeeper/oauth/scopes.rb +5 -3
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
- data/lib/doorkeeper/oauth/token_response.rb +9 -9
- data/lib/doorkeeper/oauth.rb +5 -5
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
- data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
- data/lib/doorkeeper/orm/active_record/application.rb +21 -57
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/orm/active_record.rb +6 -6
- data/lib/doorkeeper/rails/helpers.rb +1 -1
- data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
- data/lib/doorkeeper/rails/routes.rb +11 -11
- data/lib/doorkeeper/rake/db.rake +13 -13
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/secret_storing/base.rb +64 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +3 -3
- data/lib/doorkeeper.rb +69 -60
- data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
- data/lib/generators/doorkeeper/install_generator.rb +11 -9
- data/lib/generators/doorkeeper/migration_generator.rb +9 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
- data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
- data/lib/generators/doorkeeper/views_generator.rb +6 -4
- data/spec/controllers/application_metal_controller_spec.rb +24 -10
- data/spec/controllers/applications_controller_spec.rb +54 -52
- data/spec/controllers/authorizations_controller_spec.rb +139 -145
- data/spec/controllers/protected_resources_controller_spec.rb +78 -76
- data/spec/controllers/token_info_controller_spec.rb +14 -12
- data/spec/controllers/tokens_controller_spec.rb +167 -108
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/controllers/application_controller.rb +3 -1
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/controllers/home_controller.rb +5 -3
- data/spec/dummy/app/controllers/metal_controller.rb +2 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/config/application.rb +25 -1
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/production.rb +2 -0
- data/spec/dummy/config/environments/test.rb +3 -1
- data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
- data/spec/dummy/config/initializers/secret_token.rb +3 -1
- data/spec/dummy/config/initializers/session_store.rb +3 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
- data/spec/dummy/config.ru +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/script/rails +5 -3
- data/spec/factories.rb +8 -6
- data/spec/generators/application_owner_generator_spec.rb +13 -26
- data/spec/generators/confidential_applications_generator_spec.rb +12 -28
- data/spec/generators/install_generator_spec.rb +17 -15
- data/spec/generators/migration_generator_spec.rb +13 -26
- data/spec/generators/pkce_generator_spec.rb +11 -26
- data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
- data/spec/generators/templates/routes.rb +2 -0
- data/spec/generators/views_generator_spec.rb +14 -12
- data/spec/grape/grape_integration_spec.rb +34 -32
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
- data/spec/lib/config_spec.rb +268 -99
- data/spec/lib/doorkeeper_spec.rb +3 -1
- data/spec/lib/models/expirable_spec.rb +22 -8
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/revocable_spec.rb +8 -6
- data/spec/lib/models/scopes_spec.rb +27 -13
- data/spec/lib/models/secret_storable_spec.rb +135 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
- data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
- data/spec/lib/oauth/base_request_spec.rb +20 -8
- data/spec/lib/oauth/base_response_spec.rb +3 -1
- data/spec/lib/oauth/client/credentials_spec.rb +24 -22
- data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
- data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
- data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
- data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
- data/spec/lib/oauth/client_spec.rb +15 -13
- data/spec/lib/oauth/code_request_spec.rb +8 -6
- data/spec/lib/oauth/code_response_spec.rb +9 -7
- data/spec/lib/oauth/error_response_spec.rb +19 -11
- data/spec/lib/oauth/error_spec.rb +4 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
- data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
- data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
- data/spec/lib/oauth/scopes_spec.rb +63 -61
- data/spec/lib/oauth/token_request_spec.rb +79 -24
- data/spec/lib/oauth/token_response_spec.rb +40 -38
- data/spec/lib/oauth/token_spec.rb +60 -44
- data/spec/lib/request/strategy_spec.rb +3 -1
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/lib/server_spec.rb +16 -14
- data/spec/lib/stale_records_cleaner_spec.rb +17 -17
- data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
- data/spec/models/doorkeeper/access_token_spec.rb +198 -73
- data/spec/models/doorkeeper/application_spec.rb +280 -288
- data/spec/requests/applications/applications_request_spec.rb +98 -66
- data/spec/requests/applications/authorized_applications_spec.rb +20 -18
- data/spec/requests/endpoints/authorization_spec.rb +25 -23
- data/spec/requests/endpoints/token_spec.rb +38 -36
- data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
- data/spec/requests/flows/authorization_code_spec.rb +193 -151
- data/spec/requests/flows/client_credentials_spec.rb +54 -52
- data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
- data/spec/requests/flows/implicit_grant_spec.rb +27 -25
- data/spec/requests/flows/password_spec.rb +59 -55
- data/spec/requests/flows/refresh_token_spec.rb +45 -43
- data/spec/requests/flows/revoke_token_spec.rb +40 -54
- data/spec/requests/flows/skip_authorization_spec.rb +23 -21
- data/spec/requests/protected_resources/metal_spec.rb +7 -5
- data/spec/requests/protected_resources/private_api_spec.rb +35 -33
- data/spec/routing/custom_controller_routes_spec.rb +71 -65
- data/spec/routing/default_routes_spec.rb +22 -20
- data/spec/routing/scoped_routes_spec.rb +20 -18
- data/spec/spec_helper.rb +15 -13
- data/spec/spec_helper_integration.rb +3 -1
- data/spec/support/dependencies/factory_bot.rb +3 -1
- data/spec/support/doorkeeper_rspec.rb +3 -1
- data/spec/support/helpers/access_token_request_helper.rb +3 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -2
- data/spec/support/helpers/config_helper.rb +2 -0
- data/spec/support/helpers/model_helper.rb +3 -1
- data/spec/support/helpers/request_spec_helper.rb +5 -3
- data/spec/support/helpers/url_helper.rb +9 -7
- data/spec/support/http_method_shim.rb +4 -9
- data/spec/support/orm/active_record.rb +3 -1
- data/spec/support/shared/controllers_shared_context.rb +18 -16
- data/spec/support/shared/hashing_shared_context.rb +36 -0
- data/spec/support/shared/models_shared_examples.rb +12 -10
- data/spec/validators/redirect_uri_validator_spec.rb +74 -45
- data/spec/version/version_spec.rb +7 -5
- metadata +60 -26
- data/gemfiles/rails_4_2.gemfile +0 -13
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
data/lib/doorkeeper.rb
CHANGED
|
@@ -1,75 +1,84 @@
|
|
|
1
|
-
|
|
2
|
-
require 'doorkeeper/engine'
|
|
3
|
-
require 'doorkeeper/config'
|
|
1
|
+
# frozen_string_literal: true
|
|
4
2
|
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require 'doorkeeper/request/code'
|
|
9
|
-
require 'doorkeeper/request/password'
|
|
10
|
-
require 'doorkeeper/request/refresh_token'
|
|
11
|
-
require 'doorkeeper/request/token'
|
|
3
|
+
require "doorkeeper/version"
|
|
4
|
+
require "doorkeeper/engine"
|
|
5
|
+
require "doorkeeper/config"
|
|
12
6
|
|
|
13
|
-
require
|
|
14
|
-
require
|
|
15
|
-
require
|
|
16
|
-
require
|
|
7
|
+
require "doorkeeper/request/strategy"
|
|
8
|
+
require "doorkeeper/request/authorization_code"
|
|
9
|
+
require "doorkeeper/request/client_credentials"
|
|
10
|
+
require "doorkeeper/request/code"
|
|
11
|
+
require "doorkeeper/request/password"
|
|
12
|
+
require "doorkeeper/request/refresh_token"
|
|
13
|
+
require "doorkeeper/request/token"
|
|
17
14
|
|
|
18
|
-
require
|
|
19
|
-
require
|
|
20
|
-
require
|
|
21
|
-
require
|
|
22
|
-
require 'doorkeeper/oauth/helpers/scope_checker'
|
|
23
|
-
require 'doorkeeper/oauth/helpers/uri_checker'
|
|
24
|
-
require 'doorkeeper/oauth/helpers/unique_token'
|
|
15
|
+
require "doorkeeper/errors"
|
|
16
|
+
require "doorkeeper/server"
|
|
17
|
+
require "doorkeeper/request"
|
|
18
|
+
require "doorkeeper/validations"
|
|
25
19
|
|
|
26
|
-
require
|
|
27
|
-
require
|
|
28
|
-
require
|
|
29
|
-
require
|
|
30
|
-
require
|
|
31
|
-
require
|
|
32
|
-
require
|
|
33
|
-
require 'doorkeeper/oauth/pre_authorization'
|
|
34
|
-
require 'doorkeeper/oauth/base_request'
|
|
35
|
-
require 'doorkeeper/oauth/authorization_code_request'
|
|
36
|
-
require 'doorkeeper/oauth/refresh_token_request'
|
|
37
|
-
require 'doorkeeper/oauth/password_access_token_request'
|
|
20
|
+
require "doorkeeper/oauth/authorization/code"
|
|
21
|
+
require "doorkeeper/oauth/authorization/context"
|
|
22
|
+
require "doorkeeper/oauth/authorization/token"
|
|
23
|
+
require "doorkeeper/oauth/authorization/uri_builder"
|
|
24
|
+
require "doorkeeper/oauth/helpers/scope_checker"
|
|
25
|
+
require "doorkeeper/oauth/helpers/uri_checker"
|
|
26
|
+
require "doorkeeper/oauth/helpers/unique_token"
|
|
38
27
|
|
|
39
|
-
require
|
|
40
|
-
require
|
|
41
|
-
require
|
|
42
|
-
require
|
|
43
|
-
require
|
|
28
|
+
require "doorkeeper/oauth"
|
|
29
|
+
require "doorkeeper/oauth/scopes"
|
|
30
|
+
require "doorkeeper/oauth/error"
|
|
31
|
+
require "doorkeeper/oauth/base_response"
|
|
32
|
+
require "doorkeeper/oauth/code_response"
|
|
33
|
+
require "doorkeeper/oauth/token_response"
|
|
34
|
+
require "doorkeeper/oauth/error_response"
|
|
35
|
+
require "doorkeeper/oauth/pre_authorization"
|
|
36
|
+
require "doorkeeper/oauth/base_request"
|
|
37
|
+
require "doorkeeper/oauth/authorization_code_request"
|
|
38
|
+
require "doorkeeper/oauth/refresh_token_request"
|
|
39
|
+
require "doorkeeper/oauth/password_access_token_request"
|
|
44
40
|
|
|
45
|
-
require
|
|
46
|
-
require
|
|
47
|
-
require
|
|
48
|
-
require
|
|
49
|
-
require
|
|
50
|
-
require 'doorkeeper/oauth/token_introspection'
|
|
51
|
-
require 'doorkeeper/oauth/invalid_token_response'
|
|
52
|
-
require 'doorkeeper/oauth/forbidden_token_response'
|
|
41
|
+
require "doorkeeper/oauth/client_credentials/validation"
|
|
42
|
+
require "doorkeeper/oauth/client_credentials/creator"
|
|
43
|
+
require "doorkeeper/oauth/client_credentials/issuer"
|
|
44
|
+
require "doorkeeper/oauth/client_credentials/validation"
|
|
45
|
+
require "doorkeeper/oauth/client/credentials"
|
|
53
46
|
|
|
54
|
-
require
|
|
55
|
-
require
|
|
56
|
-
require
|
|
57
|
-
require
|
|
58
|
-
require
|
|
47
|
+
require "doorkeeper/oauth/client_credentials_request"
|
|
48
|
+
require "doorkeeper/oauth/code_request"
|
|
49
|
+
require "doorkeeper/oauth/token_request"
|
|
50
|
+
require "doorkeeper/oauth/client"
|
|
51
|
+
require "doorkeeper/oauth/token"
|
|
52
|
+
require "doorkeeper/oauth/token_introspection"
|
|
53
|
+
require "doorkeeper/oauth/invalid_token_response"
|
|
54
|
+
require "doorkeeper/oauth/forbidden_token_response"
|
|
59
55
|
|
|
60
|
-
require
|
|
61
|
-
require
|
|
62
|
-
require
|
|
56
|
+
require "doorkeeper/secret_storing/base"
|
|
57
|
+
require "doorkeeper/secret_storing/plain"
|
|
58
|
+
require "doorkeeper/secret_storing/sha256_hash"
|
|
59
|
+
require "doorkeeper/secret_storing/bcrypt"
|
|
63
60
|
|
|
64
|
-
require
|
|
61
|
+
require "doorkeeper/models/concerns/orderable"
|
|
62
|
+
require "doorkeeper/models/concerns/scopes"
|
|
63
|
+
require "doorkeeper/models/concerns/expirable"
|
|
64
|
+
require "doorkeeper/models/concerns/reusable"
|
|
65
|
+
require "doorkeeper/models/concerns/revocable"
|
|
66
|
+
require "doorkeeper/models/concerns/accessible"
|
|
67
|
+
require "doorkeeper/models/concerns/secret_storable"
|
|
65
68
|
|
|
66
|
-
require
|
|
67
|
-
require
|
|
69
|
+
require "doorkeeper/models/access_grant_mixin"
|
|
70
|
+
require "doorkeeper/models/access_token_mixin"
|
|
71
|
+
require "doorkeeper/models/application_mixin"
|
|
68
72
|
|
|
69
|
-
require
|
|
70
|
-
require 'doorkeeper/stale_records_cleaner'
|
|
73
|
+
require "doorkeeper/helpers/controller"
|
|
71
74
|
|
|
72
|
-
require
|
|
75
|
+
require "doorkeeper/rails/routes"
|
|
76
|
+
require "doorkeeper/rails/helpers"
|
|
77
|
+
|
|
78
|
+
require "doorkeeper/rake"
|
|
79
|
+
require "doorkeeper/stale_records_cleaner"
|
|
80
|
+
|
|
81
|
+
require "doorkeeper/orm/active_record"
|
|
73
82
|
|
|
74
83
|
module Doorkeeper
|
|
75
84
|
def self.authenticate(request, methods = Doorkeeper.configuration.access_token_methods)
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
5
|
|
|
6
6
|
module Doorkeeper
|
|
7
|
+
# Generates migration to add reference to owner of the
|
|
8
|
+
# Doorkeeper application.
|
|
9
|
+
#
|
|
7
10
|
class ApplicationOwnerGenerator < ::Rails::Generators::Base
|
|
8
11
|
include ::Rails::Generators::Migration
|
|
9
|
-
source_root File.expand_path(
|
|
10
|
-
desc
|
|
12
|
+
source_root File.expand_path("templates", __dir__)
|
|
13
|
+
desc "Provide support for client application ownership."
|
|
11
14
|
|
|
12
15
|
def application_owner
|
|
13
16
|
migration_template(
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
"add_owner_to_application_migration.rb.erb",
|
|
18
|
+
"db/migrate/add_owner_to_application.rb",
|
|
16
19
|
migration_version: migration_version
|
|
17
20
|
)
|
|
18
21
|
end
|
|
@@ -24,9 +27,7 @@ module Doorkeeper
|
|
|
24
27
|
private
|
|
25
28
|
|
|
26
29
|
def migration_version
|
|
27
|
-
|
|
28
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
29
|
-
end
|
|
30
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
end
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
5
|
|
|
6
6
|
module Doorkeeper
|
|
7
|
+
# Generates migration to add confidential column to Doorkeeper
|
|
8
|
+
# applications table.
|
|
9
|
+
#
|
|
7
10
|
class ConfidentialApplicationsGenerator < ::Rails::Generators::Base
|
|
8
11
|
include ::Rails::Generators::Migration
|
|
9
|
-
source_root File.expand_path(
|
|
10
|
-
desc
|
|
12
|
+
source_root File.expand_path("templates", __dir__)
|
|
13
|
+
desc "Add confidential column to Doorkeeper applications"
|
|
11
14
|
|
|
12
15
|
def pkce
|
|
13
16
|
migration_template(
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
"add_confidential_to_applications.rb.erb",
|
|
18
|
+
"db/migrate/add_confidential_to_applications.rb",
|
|
16
19
|
migration_version: migration_version
|
|
17
20
|
)
|
|
18
21
|
end
|
|
@@ -24,9 +27,7 @@ module Doorkeeper
|
|
|
24
27
|
private
|
|
25
28
|
|
|
26
29
|
def migration_version
|
|
27
|
-
|
|
28
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
29
|
-
end
|
|
30
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
end
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
5
|
|
|
6
6
|
module Doorkeeper
|
|
7
|
+
# Setup doorkeeper into Rails application: locales, routes, etc.
|
|
8
|
+
#
|
|
7
9
|
class InstallGenerator < ::Rails::Generators::Base
|
|
8
10
|
include ::Rails::Generators::Migration
|
|
9
|
-
source_root File.expand_path(
|
|
10
|
-
desc
|
|
11
|
+
source_root File.expand_path("templates", __dir__)
|
|
12
|
+
desc "Installs Doorkeeper."
|
|
11
13
|
|
|
12
14
|
def install
|
|
13
|
-
template
|
|
14
|
-
copy_file File.expand_path(
|
|
15
|
-
|
|
16
|
-
route
|
|
17
|
-
readme
|
|
15
|
+
template "initializer.rb", "config/initializers/doorkeeper.rb"
|
|
16
|
+
copy_file File.expand_path("../../../config/locales/en.yml", __dir__),
|
|
17
|
+
"config/locales/doorkeeper.en.yml"
|
|
18
|
+
route "use_doorkeeper"
|
|
19
|
+
readme "README"
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
5
|
|
|
6
6
|
module Doorkeeper
|
|
7
|
+
# Copies main Doorkeeper migration into parent Rails application.
|
|
8
|
+
#
|
|
7
9
|
class MigrationGenerator < ::Rails::Generators::Base
|
|
8
10
|
include ::Rails::Generators::Migration
|
|
9
|
-
source_root File.expand_path(
|
|
10
|
-
desc
|
|
11
|
+
source_root File.expand_path("templates", __dir__)
|
|
12
|
+
desc "Installs Doorkeeper migration file."
|
|
11
13
|
|
|
12
14
|
def install
|
|
13
15
|
migration_template(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
"migration.rb.erb",
|
|
17
|
+
"db/migrate/create_doorkeeper_tables.rb",
|
|
16
18
|
migration_version: migration_version
|
|
17
19
|
)
|
|
18
20
|
end
|
|
@@ -24,9 +26,7 @@ module Doorkeeper
|
|
|
24
26
|
private
|
|
25
27
|
|
|
26
28
|
def migration_version
|
|
27
|
-
|
|
28
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
29
|
-
end
|
|
29
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
5
|
|
|
6
6
|
module Doorkeeper
|
|
7
|
+
# Generates migration with PKCE required database columns for
|
|
8
|
+
# Doorkeeper tables.
|
|
9
|
+
#
|
|
7
10
|
class PkceGenerator < ::Rails::Generators::Base
|
|
8
11
|
include ::Rails::Generators::Migration
|
|
9
|
-
source_root File.expand_path(
|
|
10
|
-
desc
|
|
12
|
+
source_root File.expand_path("templates", __dir__)
|
|
13
|
+
desc "Provide support for PKCE."
|
|
11
14
|
|
|
12
15
|
def pkce
|
|
13
16
|
migration_template(
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
"enable_pkce_migration.rb.erb",
|
|
18
|
+
"db/migrate/enable_pkce.rb",
|
|
16
19
|
migration_version: migration_version
|
|
17
20
|
)
|
|
18
21
|
end
|
|
@@ -24,9 +27,7 @@ module Doorkeeper
|
|
|
24
27
|
private
|
|
25
28
|
|
|
26
29
|
def migration_version
|
|
27
|
-
|
|
28
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
29
|
-
end
|
|
30
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
end
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
5
|
|
|
6
6
|
module Doorkeeper
|
|
7
|
+
# Generates migration to add previous refresh token column to the
|
|
8
|
+
# database for Doorkeeper tables.
|
|
9
|
+
#
|
|
7
10
|
class PreviousRefreshTokenGenerator < ::Rails::Generators::Base
|
|
8
11
|
include ::Rails::Generators::Migration
|
|
9
|
-
source_root File.expand_path(
|
|
10
|
-
desc
|
|
12
|
+
source_root File.expand_path("templates", __dir__)
|
|
13
|
+
desc "Support revoke refresh token on access token use"
|
|
11
14
|
|
|
12
15
|
def self.next_migration_number(path)
|
|
13
16
|
ActiveRecord::Generators::Base.next_migration_number(path)
|
|
@@ -16,8 +19,8 @@ module Doorkeeper
|
|
|
16
19
|
def previous_refresh_token
|
|
17
20
|
if no_previous_refresh_token_column?
|
|
18
21
|
migration_template(
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
"add_previous_refresh_token_to_access_tokens.rb.erb",
|
|
23
|
+
"db/migrate/add_previous_refresh_token_to_access_tokens.rb"
|
|
21
24
|
)
|
|
22
25
|
end
|
|
23
26
|
end
|
|
@@ -25,9 +28,7 @@ module Doorkeeper
|
|
|
25
28
|
private
|
|
26
29
|
|
|
27
30
|
def migration_version
|
|
28
|
-
|
|
29
|
-
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
30
|
-
end
|
|
31
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
def no_previous_refresh_token_column?
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
Doorkeeper.configure do
|
|
2
4
|
# Change the ORM that doorkeeper will use (needs plugins)
|
|
3
5
|
orm :active_record
|
|
@@ -47,7 +49,12 @@ Doorkeeper.configure do
|
|
|
47
49
|
# access_token_expires_in 2.hours
|
|
48
50
|
|
|
49
51
|
# Assign custom TTL for access tokens. Will be used instead of access_token_expires_in
|
|
50
|
-
# option if defined. `
|
|
52
|
+
# option if defined. In case the block returns `nil` value Doorkeeper fallbacks to
|
|
53
|
+
# `access_token_expires_in` configuration option value. If you really need to issue a
|
|
54
|
+
# non-expiring access token (which is not recommended) then you need to return
|
|
55
|
+
# Float::INFINITY from this block.
|
|
56
|
+
#
|
|
57
|
+
# `context` has the following properties available:
|
|
51
58
|
#
|
|
52
59
|
# `client` - the OAuth client application (see Doorkeeper::OAuth::Client)
|
|
53
60
|
# `grant_type` - the grant type of the request (see Doorkeeper::OAuth)
|
|
@@ -64,7 +71,7 @@ Doorkeeper.configure do
|
|
|
64
71
|
|
|
65
72
|
# The controller Doorkeeper::ApplicationController inherits from.
|
|
66
73
|
# Defaults to ActionController::Base.
|
|
67
|
-
# See https://
|
|
74
|
+
# See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
|
|
68
75
|
#
|
|
69
76
|
# base_controller 'ApplicationController'
|
|
70
77
|
|
|
@@ -75,8 +82,63 @@ Doorkeeper.configure do
|
|
|
75
82
|
# doesn't updates existing token expiration time, it will create a new token instead.
|
|
76
83
|
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
|
77
84
|
#
|
|
85
|
+
# You can not enable this option together with +hash_token_secrets+.
|
|
86
|
+
#
|
|
78
87
|
# reuse_access_token
|
|
79
88
|
|
|
89
|
+
# Set a limit for token_reuse if using reuse_access_token option
|
|
90
|
+
#
|
|
91
|
+
# This option limits token_reusability to some extent.
|
|
92
|
+
# If not set then access_token will be reused unless it expires.
|
|
93
|
+
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
|
|
94
|
+
#
|
|
95
|
+
# This option should be a percentage(i.e. (0,100])
|
|
96
|
+
#
|
|
97
|
+
# token_reuse_limit 100
|
|
98
|
+
|
|
99
|
+
# Hash access and refresh tokens before persisting them.
|
|
100
|
+
# This will disable the possibility to use +reuse_access_token+
|
|
101
|
+
# since plain values can no longer be retrieved.
|
|
102
|
+
#
|
|
103
|
+
# Note: If you are already a user of doorkeeper and have existing tokens
|
|
104
|
+
# in your installation, they will be invalid without enabling the additional
|
|
105
|
+
# setting `fallback_to_plain_secrets` below.
|
|
106
|
+
#
|
|
107
|
+
# hash_token_secrets
|
|
108
|
+
# By default, token secrets will be hashed using the
|
|
109
|
+
# +Doorkeeper::Hashing::SHA256+ strategy.
|
|
110
|
+
#
|
|
111
|
+
# If you wish to use another hashing implementation, you can override
|
|
112
|
+
# this strategy as follows:
|
|
113
|
+
#
|
|
114
|
+
# hash_token_secrets using: '::Doorkeeper::Hashing::MyCustomHashImpl'
|
|
115
|
+
#
|
|
116
|
+
# Keep in mind that changing the hashing function will invalidate all existing
|
|
117
|
+
# secrets, if there are any.
|
|
118
|
+
|
|
119
|
+
# Hash application secrets before persisting them.
|
|
120
|
+
#
|
|
121
|
+
# hash_application_secrets
|
|
122
|
+
#
|
|
123
|
+
# By default, applications will be hashed
|
|
124
|
+
# with the +Doorkeeper::SecretStoring::SHA256+ strategy.
|
|
125
|
+
#
|
|
126
|
+
# If you wish to use bcrypt for application secret hashing, uncomment
|
|
127
|
+
# this line instead:
|
|
128
|
+
#
|
|
129
|
+
# hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'
|
|
130
|
+
|
|
131
|
+
# When the above option is enabled,
|
|
132
|
+
# and a hashed token or secret is not found,
|
|
133
|
+
# you can allow to fall back to another strategy.
|
|
134
|
+
# For users upgrading doorkeeper and wishing to enable hashing,
|
|
135
|
+
# you will probably want to enable the fallback to plain tokens.
|
|
136
|
+
#
|
|
137
|
+
# This will ensure that old access tokens and secrets
|
|
138
|
+
# will remain valid even if the hashing above is enabled.
|
|
139
|
+
#
|
|
140
|
+
# fallback_to_plain_secrets
|
|
141
|
+
|
|
80
142
|
# Issue access tokens with refresh token (disabled by default), you may also
|
|
81
143
|
# pass a block which accepts `context` to customize when to give a refresh
|
|
82
144
|
# token or not. Similar to `custom_access_token_expires_in`, `context` has
|
|
@@ -88,16 +150,11 @@ Doorkeeper.configure do
|
|
|
88
150
|
#
|
|
89
151
|
# use_refresh_token
|
|
90
152
|
|
|
91
|
-
# Forbids creating/updating applications with arbitrary scopes that are
|
|
92
|
-
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
|
93
|
-
# (disabled by default)
|
|
94
|
-
#
|
|
95
|
-
# enforce_configured_scopes
|
|
96
|
-
|
|
97
153
|
# Provide support for an owner to be assigned to each registered application (disabled by default)
|
|
98
154
|
# Optional parameter confirmation: true (default false) if you want to enforce ownership of
|
|
99
155
|
# a registered application
|
|
100
|
-
#
|
|
156
|
+
# NOTE: you must also run the rails g doorkeeper:application_owner generator
|
|
157
|
+
# to provide the necessary support
|
|
101
158
|
#
|
|
102
159
|
# enable_application_owner confirmation: false
|
|
103
160
|
|
|
@@ -108,6 +165,21 @@ Doorkeeper.configure do
|
|
|
108
165
|
# default_scopes :public
|
|
109
166
|
# optional_scopes :write, :update
|
|
110
167
|
|
|
168
|
+
# Define scopes_by_grant_type to restrict only certain scopes for grant_type
|
|
169
|
+
# By default, all the scopes will be available for all the grant types.
|
|
170
|
+
#
|
|
171
|
+
# Keys to this hash should be the name of grant_type and
|
|
172
|
+
# values should be the array of scopes for that grant type.
|
|
173
|
+
# Note: scopes should be from configured_scopes(i.e. deafult or optional)
|
|
174
|
+
#
|
|
175
|
+
# scopes_by_grant_type password: [:write], client_credentials: [:update]
|
|
176
|
+
|
|
177
|
+
# Forbids creating/updating applications with arbitrary scopes that are
|
|
178
|
+
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
|
179
|
+
# (disabled by default)
|
|
180
|
+
#
|
|
181
|
+
# enforce_configured_scopes
|
|
182
|
+
|
|
111
183
|
# Change the way client credentials are retrieved from the request object.
|
|
112
184
|
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
|
113
185
|
# falls back to the `:client_id` and `:client_secret` params from the `params` object.
|
|
@@ -125,9 +197,10 @@ Doorkeeper.configure do
|
|
|
125
197
|
# access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
|
|
126
198
|
|
|
127
199
|
# Change the native redirect uri for client apps
|
|
128
|
-
# When clients register with the following redirect uri, they won't be redirected to
|
|
129
|
-
# the authorizationcode will be displayed within the provider
|
|
130
|
-
# The value can be any string. Use nil to disable this feature. When disabled, clients
|
|
200
|
+
# When clients register with the following redirect uri, they won't be redirected to
|
|
201
|
+
# any server and the authorizationcode will be displayed within the provider
|
|
202
|
+
# The value can be any string. Use nil to disable this feature. When disabled, clients
|
|
203
|
+
# must providea valid URL
|
|
131
204
|
# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
|
|
132
205
|
#
|
|
133
206
|
# native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
|
|
@@ -152,6 +225,22 @@ Doorkeeper.configure do
|
|
|
152
225
|
#
|
|
153
226
|
# forbid_redirect_uri { |uri| uri.scheme.to_s.downcase == 'javascript' }
|
|
154
227
|
|
|
228
|
+
# Allows to set blank redirect URIs for Applications in case Doorkeeper configured
|
|
229
|
+
# to use URI-less OAuth grant flows like Client Credentials or Resource Owner
|
|
230
|
+
# Password Credentials. The option is on by default and checks configured grant
|
|
231
|
+
# types, but you **need** to manually drop `NOT NULL` constraint from `redirect_uri`
|
|
232
|
+
# column for `oauth_applications` database table.
|
|
233
|
+
#
|
|
234
|
+
# You can completely disable this feature with:
|
|
235
|
+
#
|
|
236
|
+
# allow_blank_redirect_uri false
|
|
237
|
+
#
|
|
238
|
+
# Or you can define your custom check:
|
|
239
|
+
#
|
|
240
|
+
# allow_blank_redirect_uri do |grant_flows, client|
|
|
241
|
+
# client.superapp?
|
|
242
|
+
# end
|
|
243
|
+
|
|
155
244
|
# Specify how authorization errors should be handled.
|
|
156
245
|
# By default, doorkeeper renders json errors when access token
|
|
157
246
|
# is invalid, expired, revoked or has invalid scopes.
|
|
@@ -165,6 +254,24 @@ Doorkeeper.configure do
|
|
|
165
254
|
#
|
|
166
255
|
# handle_auth_errors :raise
|
|
167
256
|
|
|
257
|
+
# Customize token introspection response.
|
|
258
|
+
# Allows to add your own fields to default one that are required by the OAuth spec
|
|
259
|
+
# for the introspection response. It could be `sub`, `aud` and so on.
|
|
260
|
+
# This configuration option can be a proc, lambda or any Ruby object responds
|
|
261
|
+
# to `.call` method and result of it's invocation must be a Hash.
|
|
262
|
+
#
|
|
263
|
+
# custom_introspection_response do |token, context|
|
|
264
|
+
# {
|
|
265
|
+
# "sub": "Z5O3upPC88QrAjx00dis",
|
|
266
|
+
# "aud": "https://protected.example.net/resource",
|
|
267
|
+
# "username": User.find(token.resource_owner_id).username
|
|
268
|
+
# }
|
|
269
|
+
# end
|
|
270
|
+
#
|
|
271
|
+
# or
|
|
272
|
+
#
|
|
273
|
+
# custom_introspection_response CustomIntrospectionResponder
|
|
274
|
+
|
|
168
275
|
# Specify what grant flows are enabled in array of Strings. The valid
|
|
169
276
|
# strings and the flows they enable are:
|
|
170
277
|
#
|
|
@@ -195,7 +302,7 @@ Doorkeeper.configure do
|
|
|
195
302
|
# end
|
|
196
303
|
|
|
197
304
|
# Hook into Authorization flow in order to implement Single Sign Out
|
|
198
|
-
# or add
|
|
305
|
+
# or add any other functionality.
|
|
199
306
|
#
|
|
200
307
|
# before_successful_authorization do |controller|
|
|
201
308
|
# Rails.logger.info(params.inspect)
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
|
|
2
2
|
def change
|
|
3
3
|
create_table :oauth_applications do |t|
|
|
4
|
-
t.string :name,
|
|
5
|
-
t.string :uid,
|
|
6
|
-
t.string :secret,
|
|
4
|
+
t.string :name, null: false
|
|
5
|
+
t.string :uid, null: false
|
|
6
|
+
t.string :secret, null: false
|
|
7
|
+
|
|
8
|
+
# Remove `null: false` if you are planning to use grant flows
|
|
9
|
+
# that doesn't require redirect URI to be used during authorization
|
|
10
|
+
# like Client Credentials flow or Resource Owner Password.
|
|
7
11
|
t.text :redirect_uri, null: false
|
|
8
12
|
t.string :scopes, null: false, default: ''
|
|
9
13
|
t.boolean :confidential, null: false, default: true
|
|
@@ -32,20 +36,20 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
|
|
|
32
36
|
|
|
33
37
|
create_table :oauth_access_tokens do |t|
|
|
34
38
|
t.references :resource_owner, index: true
|
|
35
|
-
t.references :application
|
|
39
|
+
t.references :application, null: false
|
|
36
40
|
|
|
37
41
|
# If you use a custom token generator you may need to change this column
|
|
38
42
|
# from string to text, so that it accepts tokens larger than 255
|
|
39
43
|
# characters. More info on custom token generators in:
|
|
40
44
|
# https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
|
|
41
45
|
#
|
|
42
|
-
# t.text
|
|
43
|
-
t.string
|
|
46
|
+
# t.text :token, null: false
|
|
47
|
+
t.string :token, null: false
|
|
44
48
|
|
|
45
49
|
t.string :refresh_token
|
|
46
50
|
t.integer :expires_in
|
|
47
51
|
t.datetime :revoked_at
|
|
48
|
-
t.datetime :created_at,
|
|
52
|
+
t.datetime :created_at, null: false
|
|
49
53
|
t.string :scopes
|
|
50
54
|
|
|
51
55
|
# If there is a previous_refresh_token column,
|
|
@@ -64,5 +68,9 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
|
|
|
64
68
|
:oauth_applications,
|
|
65
69
|
column: :application_id
|
|
66
70
|
)
|
|
71
|
+
|
|
72
|
+
# Uncomment below to ensure a valid reference to the resource owner's table
|
|
73
|
+
# add_foreign_key :oauth_access_grants, <model>, column: :resource_owner_id
|
|
74
|
+
# add_foreign_key :oauth_access_tokens, <model>, column: :resource_owner_id
|
|
67
75
|
end
|
|
68
76
|
end
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
module Generators
|
|
5
|
+
# Generates doorkeeper views for Rails application
|
|
6
|
+
#
|
|
5
7
|
class ViewsGenerator < ::Rails::Generators::Base
|
|
6
|
-
source_root File.expand_path(
|
|
8
|
+
source_root File.expand_path("../../../app/views", __dir__)
|
|
7
9
|
|
|
8
|
-
desc
|
|
10
|
+
desc "Copies default Doorkeeper views and layouts to your application."
|
|
9
11
|
|
|
10
12
|
def manifest
|
|
11
|
-
directory
|
|
12
|
-
directory
|
|
13
|
+
directory "doorkeeper", "app/views/doorkeeper"
|
|
14
|
+
directory "layouts/doorkeeper", "app/views/layouts/doorkeeper"
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
17
|
end
|