doorkeeper-sequel 1.2.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/.gitignore +10 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +24 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +172 -0
- data/LICENSE +21 -0
- data/README.md +76 -0
- data/Rakefile +56 -0
- data/config/locales/en.yml +16 -0
- data/doorkeeper-sequel.gemspec +32 -0
- data/gemfiles/rails-4.2.gemfile +11 -0
- data/gemfiles/rails-5.0.gemfile +11 -0
- data/lib/doorkeeper/orm/sequel/access_grant.rb +9 -0
- data/lib/doorkeeper/orm/sequel/access_token.rb +32 -0
- data/lib/doorkeeper/orm/sequel/application.rb +18 -0
- data/lib/doorkeeper/orm/sequel/models/access_grant_mixin.rb +50 -0
- data/lib/doorkeeper/orm/sequel/models/access_token_mixin.rb +163 -0
- data/lib/doorkeeper/orm/sequel/models/application_mixin.rb +70 -0
- data/lib/doorkeeper/orm/sequel/models/concerns/ownership.rb +19 -0
- data/lib/doorkeeper/orm/sequel/models/concerns/sequel_compat.rb +40 -0
- data/lib/doorkeeper/orm/sequel/validators/redirect_uri_validator.rb +49 -0
- data/lib/doorkeeper/orm/sequel.rb +18 -0
- data/lib/doorkeeper-sequel/gem_version.rb +13 -0
- data/lib/doorkeeper-sequel/version.rb +7 -0
- data/lib/doorkeeper-sequel.rb +18 -0
- data/lib/generators/doorkeeper/sequel/application_owner_generator.rb +23 -0
- data/lib/generators/doorkeeper/sequel/migration_generator.rb +23 -0
- data/lib/generators/doorkeeper/sequel/previous_refresh_token_generator.rb +23 -0
- data/lib/generators/doorkeeper/sequel/templates/add_owner_to_application.rb +9 -0
- data/lib/generators/doorkeeper/sequel/templates/add_previous_refresh_token_to_access_tokens.rb +7 -0
- data/lib/generators/doorkeeper/sequel/templates/migration.rb +59 -0
- data/spec/controllers/application_metal_controller.rb +10 -0
- data/spec/controllers/applications_controller_spec.rb +58 -0
- data/spec/controllers/authorizations_controller_spec.rb +189 -0
- data/spec/controllers/protected_resources_controller_spec.rb +300 -0
- data/spec/controllers/token_info_controller_spec.rb +52 -0
- data/spec/controllers/tokens_controller_spec.rb +88 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +7 -0
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
- data/spec/dummy/app/controllers/home_controller.rb +17 -0
- data/spec/dummy/app/controllers/metal_controller.rb +11 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +5 -0
- data/spec/dummy/app/models/user.rb +11 -0
- data/spec/dummy/app/views/home/index.html.erb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +9 -0
- data/spec/dummy/config/database.yml +15 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +62 -0
- data/spec/dummy/config/environments/test.rb +44 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/db.rb +74 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +96 -0
- data/spec/dummy/config/initializers/secret_token.rb +9 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
- data/spec/dummy/config/routes.rb +52 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +60 -0
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +7 -0
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +11 -0
- data/spec/dummy/db/schema.rb +67 -0
- data/spec/dummy/log/test.log +19813 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-T/-TZF6Ae6YipbyKuHghb9wlTx4_b9itbSHRc_2PmqjiU.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/0p/0pa3wNbGHqFC6gxrMvdOJiP6gPwFv9VJ_npjEfRWxAE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2e/2eYh115US2lIRhM2KTEaJFa6aV_cX8iv6JAdjuq0Uio.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3P/3PoguHEOEeItUjmwC74MWLLP-_Ijow7798bF5U6K2dw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6b/6b0anrSo7Fvoc05t4Ca0zZmfS_cpERy1DsG3ea6lBOg.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/BA/BAC3ZaGoeZ9Od-kKg-UQYelvRgsCa0H72-52nLdcTNw.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Bw/Bw6Nimjvy5Yv1AYbZb1t-v0eMNhv-bhwBzR-b5mY7FU.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Fq/FqQWjMAz8yjZQlMC_dUsztaOxGruI2IXyGAAUF9SvQ0.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/J_/J_D9clwKidN28hnVB1O3zEfKDwg90Usdb5ToKiPq_aw.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ji/JitNKkP1dYdu9ObSdIkkEAsiFxEmRO5oy1UIyhT_hYs.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Jq/JqTLVvnY2AgGkHftWPwqt_HkbwhYRsmgHxk37VqKJAY.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QX/QXcp8DweOJ6BfMedGMfeHvVXv2hjDIleln1LSJk7vOE.cache +2 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Qy/Qy1ldbz6vKa_fv4E4ByxWslKFoV1qReQR5DKJ525z88.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rl/RlCJ_X5xFsE3VBDhkYrY7r_R6sMgiAc03cT8nr7Q2vY.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ta/TaYxNn81MhqC3DnMC6_y_Q7xap5Ntn4ggFo94EUaiak.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wq/WqbLVKOcTMZtttygYt_ncr1mGIDrzevSTaPGNmzV1D8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/YF/YF60qiQ28QMoYDrLmrbHWZr7X7bl5MxVPR5QrrVCFak.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Yf/YfJJZvm_NONHd4eCasDibCcRapZ_WYIO5MUxSUUbYFk.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Z0/Z0e47cT2a-21U-w-3gkbgqC3o5jWnEzOB8vW06aJH1E.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_u/_uy-z8SVnhffUNelRxbPDL2aAUPb_GbqREXVsfy8uGc.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/dL/dL7SLUWUIeVdyA1UuH-rvif0nzesOar3LdEtqzdb4bE.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/f8/f8WT8jqR1qNIdQaRDpXbyLN7E5AWkbYFBwdh9Ozk7gk.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hk/hk2YB6skvc72qL4IzzQKU8Emyfe5vARjoD1bvQTw4zE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/iO/iOpDp_7ZvBNO5WIpTmqNewUl9bB2satqXWulyNvAaX8.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ii/iiJRBZIsxKiwyzU_Z7UtQeUTXMRJRPTreTKRvAWO7_8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mj/mjuMepngMLrtgilLlJ9oTTSqoGO1YUww1rXphQ1pOm4.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qo/qo6SpT75QykYB63Aqq5bgzpXyNU1Y4dGFvCCJgoWQpE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sp/sprzBMBliJDI__s-0D3q82tn1MpBkFV0N651hTr3XE8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tM/tM6A7CR8QluP_u4u59vN1GjSZGNqNH3TXkkNzb9EPXA.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/vO/vOXN0mER62j4JiPpMTSVS7MMqs0067cZx14vD5B8qiQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zz/zzlQ_kom0liFOvGYDcjtVw6yAHOyA-bbzP8f0e_Tq1A.cache +1 -0
- data/spec/factories.rb +28 -0
- data/spec/generators/application_owner_generator_spec.rb +20 -0
- data/spec/generators/migration_generator_spec.rb +20 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +20 -0
- data/spec/generators/templates/routes.rb +3 -0
- data/spec/generators/tmp/dummy/db/migrate/20161012132809_create_doorkeeper_tables.rb +59 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +24 -0
- data/spec/lib/config_spec.rb +334 -0
- data/spec/lib/doorkeeper_spec.rb +28 -0
- data/spec/lib/models/expirable_spec.rb +51 -0
- data/spec/lib/models/revocable_spec.rb +59 -0
- data/spec/lib/models/scopes_spec.rb +43 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +42 -0
- data/spec/lib/oauth/authorization_code_request_spec.rb +80 -0
- data/spec/lib/oauth/client/credentials_spec.rb +47 -0
- data/spec/lib/oauth/client/methods_spec.rb +54 -0
- data/spec/lib/oauth/client_credentials/creator_spec.rb +44 -0
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +86 -0
- data/spec/lib/oauth/client_credentials/validation_spec.rb +54 -0
- data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
- data/spec/lib/oauth/client_credentials_request_spec.rb +104 -0
- data/spec/lib/oauth/client_spec.rb +39 -0
- data/spec/lib/oauth/code_request_spec.rb +45 -0
- data/spec/lib/oauth/code_response_spec.rb +34 -0
- data/spec/lib/oauth/error_response_spec.rb +61 -0
- data/spec/lib/oauth/error_spec.rb +23 -0
- data/spec/lib/oauth/forbidden_token_response_spec.rb +23 -0
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +64 -0
- data/spec/lib/oauth/helpers/unique_token_spec.rb +20 -0
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +104 -0
- data/spec/lib/oauth/invalid_token_response_spec.rb +28 -0
- data/spec/lib/oauth/password_access_token_request_spec.rb +90 -0
- data/spec/lib/oauth/pre_authorization_spec.rb +155 -0
- data/spec/lib/oauth/refresh_token_request_spec.rb +154 -0
- data/spec/lib/oauth/scopes_spec.rb +122 -0
- data/spec/lib/oauth/token_request_spec.rb +98 -0
- data/spec/lib/oauth/token_response_spec.rb +85 -0
- data/spec/lib/oauth/token_spec.rb +116 -0
- data/spec/lib/request/strategy_spec.rb +53 -0
- data/spec/lib/server_spec.rb +52 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
- data/spec/models/doorkeeper/access_token_spec.rb +394 -0
- data/spec/models/doorkeeper/application_spec.rb +179 -0
- data/spec/requests/applications/applications_request_spec.rb +94 -0
- data/spec/requests/applications/authorized_applications_spec.rb +30 -0
- data/spec/requests/endpoints/authorization_spec.rb +72 -0
- data/spec/requests/endpoints/token_spec.rb +64 -0
- data/spec/requests/flows/authorization_code_errors_spec.rb +66 -0
- data/spec/requests/flows/authorization_code_spec.rb +156 -0
- data/spec/requests/flows/client_credentials_spec.rb +58 -0
- data/spec/requests/flows/implicit_grant_errors_spec.rb +32 -0
- data/spec/requests/flows/implicit_grant_spec.rb +61 -0
- data/spec/requests/flows/password_spec.rb +115 -0
- data/spec/requests/flows/refresh_token_spec.rb +174 -0
- data/spec/requests/flows/revoke_token_spec.rb +157 -0
- data/spec/requests/flows/skip_authorization_spec.rb +59 -0
- data/spec/requests/protected_resources/metal_spec.rb +14 -0
- data/spec/requests/protected_resources/private_api_spec.rb +81 -0
- data/spec/routing/custom_controller_routes_spec.rb +71 -0
- data/spec/routing/default_routes_spec.rb +35 -0
- data/spec/routing/scoped_routes_spec.rb +31 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/spec_helper_integration.rb +50 -0
- data/spec/stubs/config/application.rb +29 -0
- data/spec/stubs/config/initializers/db.rb +74 -0
- data/spec/stubs/generators/application_owner_generator_spec.rb +20 -0
- data/spec/stubs/generators/migration_generator_spec.rb +20 -0
- data/spec/stubs/generators/previous_refresh_token_generator_spec.rb +20 -0
- data/spec/stubs/generators/tmp/dummy/db/migrate/20161012132810_add_owner_to_application.rb +9 -0
- data/spec/stubs/models/user.rb +11 -0
- data/spec/stubs/spec_helper_integration.rb +50 -0
- data/spec/stubs/support/sequel.rb +0 -0
- data/spec/support/dependencies/factory_girl.rb +2 -0
- data/spec/support/helpers/access_token_request_helper.rb +11 -0
- data/spec/support/helpers/authorization_request_helper.rb +41 -0
- data/spec/support/helpers/config_helper.rb +9 -0
- data/spec/support/helpers/model_helper.rb +67 -0
- data/spec/support/helpers/request_spec_helper.rb +76 -0
- data/spec/support/helpers/url_helper.rb +55 -0
- data/spec/support/http_method_shim.rb +24 -0
- data/spec/support/orm/active_record.rb +3 -0
- data/spec/support/orm/sequel.rb +0 -0
- data/spec/support/shared/controllers_shared_context.rb +69 -0
- data/spec/support/shared/models_shared_examples.rb +52 -0
- data/spec/validators/redirect_uri_validator_spec.rb +78 -0
- metadata +570 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Orm
|
|
3
|
+
module Sequel
|
|
4
|
+
module AccessTokenMixin
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
include SequelCompat
|
|
8
|
+
include OAuth::Helpers
|
|
9
|
+
include Models::Expirable
|
|
10
|
+
include Models::Revocable
|
|
11
|
+
include Models::Accessible
|
|
12
|
+
include Models::Scopes
|
|
13
|
+
|
|
14
|
+
included do
|
|
15
|
+
plugin :validation_helpers
|
|
16
|
+
plugin :timestamps
|
|
17
|
+
|
|
18
|
+
many_to_one :application, class: 'Doorkeeper::Application'
|
|
19
|
+
|
|
20
|
+
attr_writer :use_refresh_token
|
|
21
|
+
|
|
22
|
+
set_allowed_columns :application_id, :resource_owner_id, :expires_in,
|
|
23
|
+
:scopes, :use_refresh_token, :previous_refresh_token
|
|
24
|
+
|
|
25
|
+
def before_validation
|
|
26
|
+
if new?
|
|
27
|
+
generate_token
|
|
28
|
+
generate_refresh_token if use_refresh_token?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def validate
|
|
35
|
+
super
|
|
36
|
+
validates_presence [:token]
|
|
37
|
+
validates_unique [:token]
|
|
38
|
+
|
|
39
|
+
validates_unique [:refresh_token] if use_refresh_token?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def application_id?
|
|
43
|
+
application_id.present?
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
module ClassMethods
|
|
48
|
+
def by_token(token)
|
|
49
|
+
find(token: token.to_s)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def by_refresh_token(refresh_token)
|
|
53
|
+
find(refresh_token: refresh_token.to_s)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def revoke_all_for(application_id, resource_owner)
|
|
57
|
+
where(application_id: application_id,
|
|
58
|
+
resource_owner_id: resource_owner.id,
|
|
59
|
+
revoked_at: nil)
|
|
60
|
+
.each(&:revoke)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def matching_token_for(application, resource_owner_or_id, scopes)
|
|
64
|
+
resource_owner_id = if resource_owner_or_id.respond_to?(:to_key)
|
|
65
|
+
resource_owner_or_id.id
|
|
66
|
+
else
|
|
67
|
+
resource_owner_or_id
|
|
68
|
+
end
|
|
69
|
+
token = last_authorized_token_for(application.try(:id), resource_owner_id)
|
|
70
|
+
if token && scopes_match?(token.scopes, scopes, application.try(:scopes))
|
|
71
|
+
token
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def scopes_match?(token_scopes, param_scopes, app_scopes)
|
|
76
|
+
(!token_scopes.present? && !param_scopes.present?) ||
|
|
77
|
+
Doorkeeper::OAuth::Helpers::ScopeChecker.match?(
|
|
78
|
+
token_scopes.to_s,
|
|
79
|
+
param_scopes,
|
|
80
|
+
app_scopes
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def find_or_create_for(application, resource_owner_id, scopes, expires_in, use_refresh_token)
|
|
85
|
+
if Doorkeeper.configuration.reuse_access_token
|
|
86
|
+
access_token = matching_token_for(application, resource_owner_id, scopes)
|
|
87
|
+
if access_token && !access_token.expired?
|
|
88
|
+
return access_token
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
create!(
|
|
93
|
+
application_id: application.try(:id),
|
|
94
|
+
resource_owner_id: resource_owner_id,
|
|
95
|
+
scopes: scopes.to_s,
|
|
96
|
+
expires_in: expires_in,
|
|
97
|
+
use_refresh_token: use_refresh_token
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def last_authorized_token_for(application_id, resource_owner_id)
|
|
102
|
+
where(application_id: application_id,
|
|
103
|
+
resource_owner_id: resource_owner_id,
|
|
104
|
+
revoked_at: nil)
|
|
105
|
+
.send(order_method, created_at_desc)
|
|
106
|
+
.first
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def token_type
|
|
111
|
+
'bearer'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def use_refresh_token?
|
|
115
|
+
!!@use_refresh_token
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def as_json(_options = {})
|
|
119
|
+
{
|
|
120
|
+
resource_owner_id: resource_owner_id,
|
|
121
|
+
scopes: scopes,
|
|
122
|
+
expires_in_seconds: expires_in_seconds,
|
|
123
|
+
application: { uid: application.try(:uid) },
|
|
124
|
+
created_at: created_at.to_i
|
|
125
|
+
}
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# It indicates whether the tokens have the same credential
|
|
129
|
+
def same_credential?(access_token)
|
|
130
|
+
application_id == access_token.application_id &&
|
|
131
|
+
resource_owner_id == access_token.resource_owner_id
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def acceptable?(scopes)
|
|
135
|
+
accessible? && includes_scope?(*scopes)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
private
|
|
139
|
+
|
|
140
|
+
def generate_refresh_token
|
|
141
|
+
self[:refresh_token] = UniqueToken.generate
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def generate_token
|
|
145
|
+
self[:created_at] ||= Time.now.utc
|
|
146
|
+
|
|
147
|
+
generator = Doorkeeper.configuration.access_token_generator.constantize
|
|
148
|
+
self[:token] = generator.generate(
|
|
149
|
+
resource_owner_id: resource_owner_id,
|
|
150
|
+
scopes: scopes,
|
|
151
|
+
application: application,
|
|
152
|
+
expires_in: expires_in,
|
|
153
|
+
created_at: created_at
|
|
154
|
+
)
|
|
155
|
+
rescue NoMethodError
|
|
156
|
+
raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
|
|
157
|
+
rescue NameError
|
|
158
|
+
raise Errors::TokenGeneratorNotFound, "#{generator} not found"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require_relative '../validators/redirect_uri_validator'
|
|
2
|
+
|
|
3
|
+
module Doorkeeper
|
|
4
|
+
module Orm
|
|
5
|
+
module Sequel
|
|
6
|
+
module ApplicationMixin
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
include SequelCompat
|
|
10
|
+
include OAuth::Helpers
|
|
11
|
+
include Models::Scopes
|
|
12
|
+
include Doorkeeper::Orm::Sequel::RedirectUriValidator
|
|
13
|
+
|
|
14
|
+
included do
|
|
15
|
+
plugin :validation_helpers
|
|
16
|
+
plugin :timestamps
|
|
17
|
+
plugin :association_dependencies
|
|
18
|
+
|
|
19
|
+
one_to_many :access_grants, class: 'Doorkeeper::AccessGrant'
|
|
20
|
+
one_to_many :access_tokens, class: 'Doorkeeper::AccessToken'
|
|
21
|
+
|
|
22
|
+
add_association_dependencies access_grants: :delete, access_tokens: :delete
|
|
23
|
+
|
|
24
|
+
set_allowed_columns :name, :redirect_uri, :scopes
|
|
25
|
+
|
|
26
|
+
def before_validation
|
|
27
|
+
generate_uid
|
|
28
|
+
generate_secret
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def validate
|
|
33
|
+
super
|
|
34
|
+
validates_presence [:name, :secret, :uid]
|
|
35
|
+
validates_unique [:uid]
|
|
36
|
+
validates_redirect_uri :redirect_uri
|
|
37
|
+
|
|
38
|
+
if respond_to?(:validate_owner?)
|
|
39
|
+
validates_presence [:owner_id] if validate_owner?
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
module ClassMethods
|
|
45
|
+
def by_uid_and_secret(uid, secret)
|
|
46
|
+
find(uid: uid.to_s, secret: secret.to_s)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def by_uid(uid)
|
|
50
|
+
find(uid: uid.to_s)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def has_scopes?
|
|
57
|
+
Doorkeeper::Application.columns.include?('scopes')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def generate_uid
|
|
61
|
+
self.uid = UniqueToken.generate if uid.blank? && new?
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def generate_secret
|
|
65
|
+
self.secret = UniqueToken.generate if secret.blank? && new?
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Orm
|
|
3
|
+
module Sequel
|
|
4
|
+
module Ownership
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
plugin :polymorphic
|
|
9
|
+
|
|
10
|
+
many_to_one :owner, polymorphic: true
|
|
11
|
+
|
|
12
|
+
def validate_owner?
|
|
13
|
+
Doorkeeper.configuration.confirm_application_owner?
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Orm
|
|
3
|
+
module Sequel
|
|
4
|
+
module SequelCompat
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
# ActiveRecord methods used by Doorkeeper outside the ORM.
|
|
8
|
+
# Should be extracted at the architectural level.
|
|
9
|
+
included do
|
|
10
|
+
plugin :active_model
|
|
11
|
+
|
|
12
|
+
self.raise_on_save_failure = false
|
|
13
|
+
|
|
14
|
+
def update_attribute(column, value)
|
|
15
|
+
self[column] = value
|
|
16
|
+
save(columns: [column.to_sym], validate: false)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update_attributes(*args)
|
|
20
|
+
update(*args)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def save!(*)
|
|
24
|
+
save(raise_on_failure: true)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def transaction(opts = {}, &block)
|
|
28
|
+
db.transaction(opts, &block)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module ClassMethods
|
|
33
|
+
def create!(values = {}, &block)
|
|
34
|
+
new(values, &block).save(raise_on_failure: true)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Orm
|
|
3
|
+
module Sequel
|
|
4
|
+
module RedirectUriValidator
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
def validates_redirect_uri(attribute)
|
|
9
|
+
value = self[attribute]
|
|
10
|
+
|
|
11
|
+
if value.blank?
|
|
12
|
+
errors.add(attribute, I18n.t(:blank, scope: redirect_uri_errors))
|
|
13
|
+
else
|
|
14
|
+
value.split.each do |val|
|
|
15
|
+
uri = ::URI.parse(val)
|
|
16
|
+
return true if native_redirect_uri?(uri)
|
|
17
|
+
errors.add(attribute, I18n.t(:fragment_present, scope: redirect_uri_errors)) unless uri.fragment.nil?
|
|
18
|
+
errors.add(attribute, I18n.t(:relative_uri, scope: redirect_uri_errors)) if uri.scheme.nil? || uri.host.nil?
|
|
19
|
+
errors.add(attribute, I18n.t(:secured_uri, scope: redirect_uri_errors)) if invalid_ssl_uri?(uri)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
rescue URI::InvalidURIError
|
|
23
|
+
errors.add(attribute, I18n.t(:invalid_uri, scope: redirect_uri_errors))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def native_redirect_uri?(uri)
|
|
29
|
+
native_redirect_uri.present? && uri.to_s == native_redirect_uri.to_s
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def invalid_ssl_uri?(uri)
|
|
33
|
+
forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
|
|
34
|
+
forces_ssl && uri.try(:scheme) == 'http'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def native_redirect_uri
|
|
38
|
+
Doorkeeper.configuration.native_redirect_uri
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# TODO: plugin? Merge to DEFAULT_OPTIONS?
|
|
42
|
+
def redirect_uri_errors
|
|
43
|
+
'sequel.errors.models.doorkeeper/application.attributes.redirect_uri'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Orm
|
|
3
|
+
module Sequel
|
|
4
|
+
def self.initialize_models!
|
|
5
|
+
require 'doorkeeper/orm/sequel/models/concerns/sequel_compat'
|
|
6
|
+
require 'doorkeeper/orm/sequel/access_grant'
|
|
7
|
+
require 'doorkeeper/orm/sequel/access_token'
|
|
8
|
+
require 'doorkeeper/orm/sequel/application'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.initialize_application_owner!
|
|
12
|
+
require 'doorkeeper/orm/sequel/models/concerns/ownership'
|
|
13
|
+
|
|
14
|
+
Doorkeeper::Application.send :include, Doorkeeper::Orm::Sequel::Ownership
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'doorkeeper-sequel/version'
|
|
2
|
+
|
|
3
|
+
require 'doorkeeper'
|
|
4
|
+
|
|
5
|
+
require 'doorkeeper/orm/sequel'
|
|
6
|
+
|
|
7
|
+
module DoorkeeperSequel
|
|
8
|
+
def load_locales
|
|
9
|
+
locales_dir = File.expand_path('../../config/locales', __FILE__)
|
|
10
|
+
locales = Dir[File.join(locales_dir, '*.yml')]
|
|
11
|
+
|
|
12
|
+
I18n.load_path |= locales
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module_function :load_locales
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
DoorkeeperSequel.load_locales
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Sequel
|
|
3
|
+
class ApplicationOwnerGenerator < ::Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
5
|
+
|
|
6
|
+
desc 'Provide support for client application ownership.'
|
|
7
|
+
|
|
8
|
+
def install
|
|
9
|
+
copy_file 'add_owner_to_application.rb', migration_file_name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def migration_file_name
|
|
15
|
+
"db/migrate/#{migration_timestamp}_add_owner_to_application.rb"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def migration_timestamp
|
|
19
|
+
Time.current.strftime('%Y%m%d%H%M%S')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Sequel
|
|
3
|
+
class MigrationGenerator < ::Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
5
|
+
|
|
6
|
+
desc 'Installs Doorkeeper Sequel migration file.'
|
|
7
|
+
|
|
8
|
+
def install
|
|
9
|
+
copy_file 'migration.rb', migration_file_name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def migration_file_name
|
|
15
|
+
"db/migrate/#{migration_timestamp}_create_doorkeeper_tables.rb"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def migration_timestamp
|
|
19
|
+
Time.current.strftime('%Y%m%d%H%M%S')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Sequel
|
|
3
|
+
class PreviousRefreshTokenGenerator < ::Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
5
|
+
|
|
6
|
+
desc 'Support revoke refresh token on access token use'
|
|
7
|
+
|
|
8
|
+
def install
|
|
9
|
+
copy_file 'add_previous_refresh_token_to_access_tokens.rb', migration_file_name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def migration_file_name
|
|
15
|
+
"db/migrate/#{migration_timestamp}_add_previous_refresh_token_to_access_tokens.rb"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def migration_timestamp
|
|
19
|
+
Time.current.strftime('%Y%m%d%H%M%S')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Sequel.migration do
|
|
2
|
+
change do
|
|
3
|
+
create_table :oauth_applications do
|
|
4
|
+
primary_key :id
|
|
5
|
+
|
|
6
|
+
column :name, String, size: 255, null: false
|
|
7
|
+
column :uid, String, size: 255, null: false, index: { unique: true }
|
|
8
|
+
column :secret, String, size: 255, null: false
|
|
9
|
+
|
|
10
|
+
column :scopes, String, size: 255, null: false, default: ''
|
|
11
|
+
column :redirect_uri, String
|
|
12
|
+
|
|
13
|
+
column :created_at, DateTime
|
|
14
|
+
column :updated_at, DateTime
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
create_table :oauth_access_grants do
|
|
18
|
+
primary_key :id
|
|
19
|
+
foreign_key :application_id, :oauth_applications, null: false, on_delete: :cascade
|
|
20
|
+
|
|
21
|
+
column :resource_owner_id, Integer, null: false
|
|
22
|
+
|
|
23
|
+
column :token, String, size: 255, null: false, index: { unique: true }
|
|
24
|
+
column :expires_in, Integer, null: false
|
|
25
|
+
column :redirect_uri, String, null: false
|
|
26
|
+
column :created_at, DateTime, null: false
|
|
27
|
+
column :revoked_at, DateTime
|
|
28
|
+
column :scopes, String, size: 255
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
create_table :oauth_access_tokens do
|
|
32
|
+
primary_key :id
|
|
33
|
+
foreign_key :application_id, :oauth_applications, null: false, on_delete: :cascade
|
|
34
|
+
|
|
35
|
+
column :resource_owner_id, Integer, index: true
|
|
36
|
+
|
|
37
|
+
# If you use a custom token generator you may need to change this column
|
|
38
|
+
# from string to text, so that it accepts tokens larger than 255
|
|
39
|
+
# characters. More info on custom token generators in:
|
|
40
|
+
# https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
|
|
41
|
+
#
|
|
42
|
+
# column :token, String, null: false
|
|
43
|
+
column :token, String, size: 255, null: false, index: { unique: true }
|
|
44
|
+
|
|
45
|
+
column :refresh_token, String, size: 255, index: { unique: true }
|
|
46
|
+
# If there is a previous_refresh_token column,
|
|
47
|
+
# refresh tokens will be revoked after a related access token is used.
|
|
48
|
+
# If there is no previous_refresh_token column,
|
|
49
|
+
# previous tokens are revoked as soon as a new access token is created.
|
|
50
|
+
# Comment out this line if you'd rather have refresh tokens
|
|
51
|
+
# instantly revoked.
|
|
52
|
+
column :previous_refresh_token, String, size: 255, null: false, default: ''
|
|
53
|
+
column :expires_in, Integer
|
|
54
|
+
column :revoked_at, DateTime
|
|
55
|
+
column :created_at, DateTime, null: false
|
|
56
|
+
column :scopes, String, size: 255
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'spec_helper_integration'
|
|
2
|
+
|
|
3
|
+
module Doorkeeper
|
|
4
|
+
describe ApplicationsController do
|
|
5
|
+
context 'when admin is not authenticated' do
|
|
6
|
+
before do
|
|
7
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(proc do
|
|
8
|
+
redirect_to main_app.root_url
|
|
9
|
+
end)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'redirects as set in Doorkeeper.authenticate_admin' do
|
|
13
|
+
get :index
|
|
14
|
+
expect(response).to redirect_to(controller.main_app.root_url)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'does not create application' do
|
|
18
|
+
expect do
|
|
19
|
+
post :create, doorkeeper_application: {
|
|
20
|
+
name: 'Example',
|
|
21
|
+
redirect_uri: 'https://example.com' }
|
|
22
|
+
end.to_not change { Doorkeeper::Application.count }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when admin is authenticated' do
|
|
27
|
+
before do
|
|
28
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(arg) { true })
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'creates application' do
|
|
32
|
+
expect do
|
|
33
|
+
post :create, doorkeeper_application: {
|
|
34
|
+
name: 'Example',
|
|
35
|
+
redirect_uri: 'https://example.com' }
|
|
36
|
+
end.to change { Doorkeeper::Application.count }.by(1)
|
|
37
|
+
expect(response).to be_redirect
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'does not allow mass assignment of uid or secret' do
|
|
41
|
+
application = FactoryGirl.create(:application)
|
|
42
|
+
put :update, id: application.id, doorkeeper_application: {
|
|
43
|
+
uid: '1A2B3C4D',
|
|
44
|
+
secret: '1A2B3C4D' }
|
|
45
|
+
|
|
46
|
+
expect(application.reload.uid).not_to eq '1A2B3C4D'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'updates application' do
|
|
50
|
+
application = FactoryGirl.create(:application)
|
|
51
|
+
put :update, id: application.id, doorkeeper_application: {
|
|
52
|
+
name: 'Example',
|
|
53
|
+
redirect_uri: 'https://example.com' }
|
|
54
|
+
expect(application.reload.name).to eq 'Example'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|