doorkeeper 4.4.3 → 5.0.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +16 -0
- data/.travis.yml +7 -0
- data/Appraisals +2 -2
- data/Dangerfile +64 -0
- data/Gemfile +1 -1
- data/NEWS.md +98 -8
- data/README.md +110 -12
- data/Rakefile +6 -0
- data/UPGRADE.md +2 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +6 -3
- data/app/controllers/doorkeeper/application_metal_controller.rb +6 -0
- data/app/controllers/doorkeeper/applications_controller.rb +46 -24
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +21 -2
- data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
- data/app/controllers/doorkeeper/tokens_controller.rb +4 -6
- data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
- data/app/validators/redirect_uri_validator.rb +5 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +25 -24
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +17 -7
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +6 -6
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +10 -1
- data/doorkeeper.gemspec +25 -26
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/gemfiles/rails_master.gemfile +4 -1
- data/lib/doorkeeper/config.rb +81 -40
- data/lib/doorkeeper/engine.rb +6 -0
- data/lib/doorkeeper/errors.rb +17 -3
- data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
- data/lib/doorkeeper/grape/helpers.rb +3 -1
- data/lib/doorkeeper/helpers/controller.rb +9 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +73 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +44 -25
- data/lib/doorkeeper/models/application_mixin.rb +2 -0
- data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
- data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +3 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +33 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +38 -14
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
- data/lib/doorkeeper/oauth/authorization_code_request.rb +29 -2
- data/lib/doorkeeper/oauth/base_request.rb +22 -9
- data/lib/doorkeeper/oauth/base_response.rb +2 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +3 -1
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +4 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -5
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -3
- data/lib/doorkeeper/oauth/code_request.rb +2 -0
- data/lib/doorkeeper/oauth/code_response.rb +2 -0
- data/lib/doorkeeper/oauth/error.rb +2 -0
- data/lib/doorkeeper/oauth/error_response.rb +21 -3
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +5 -2
- data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +43 -11
- data/lib/doorkeeper/oauth/refresh_token_request.rb +16 -3
- data/lib/doorkeeper/oauth/scopes.rb +3 -1
- data/lib/doorkeeper/oauth/token.rb +7 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +4 -2
- data/lib/doorkeeper/oauth/token_request.rb +2 -0
- data/lib/doorkeeper/oauth/token_response.rb +6 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/application.rb +75 -12
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +4 -0
- data/lib/doorkeeper/rails/helpers.rb +6 -4
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
- data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
- data/lib/doorkeeper/rails/routes.rb +23 -8
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/authorization_code.rb +1 -1
- data/lib/doorkeeper/request/client_credentials.rb +1 -1
- data/lib/doorkeeper/request/code.rb +1 -1
- data/lib/doorkeeper/request/password.rb +1 -1
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/request/strategy.rb +2 -0
- data/lib/doorkeeper/request/token.rb +1 -1
- data/lib/doorkeeper/request.rb +29 -34
- data/lib/doorkeeper/server.rb +2 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
- data/lib/doorkeeper/validations.rb +2 -0
- data/lib/doorkeeper/version.rb +6 -24
- data/lib/doorkeeper.rb +20 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +23 -18
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +96 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -3
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +123 -14
- data/spec/controllers/authorizations_controller_spec.rb +334 -51
- data/spec/controllers/protected_resources_controller_spec.rb +60 -18
- data/spec/controllers/token_info_controller_spec.rb +4 -12
- data/spec/controllers/tokens_controller_spec.rb +17 -20
- data/spec/dummy/Rakefile +1 -1
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
- data/spec/dummy/app/controllers/home_controller.rb +1 -2
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/config/boot.rb +2 -4
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +5 -6
- data/spec/dummy/config/initializers/doorkeeper.rb +12 -6
- data/spec/dummy/config/initializers/new_framework_defaults.rb +2 -0
- data/spec/dummy/config/initializers/secret_token.rb +1 -1
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/config.ru +1 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
- data/spec/dummy/db/schema.rb +36 -36
- data/spec/dummy/script/rails +4 -3
- data/spec/factories.rb +6 -6
- data/spec/generators/application_owner_generator_spec.rb +1 -1
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +5 -2
- data/spec/generators/migration_generator_spec.rb +1 -1
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
- data/spec/generators/templates/routes.rb +0 -1
- data/spec/generators/views_generator_spec.rb +2 -2
- data/spec/grape/grape_integration_spec.rb +2 -2
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +105 -39
- data/spec/lib/doorkeeper_spec.rb +6 -131
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +0 -2
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +17 -7
- data/spec/lib/oauth/base_request_spec.rb +49 -11
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +2 -4
- data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +24 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -3
- data/spec/lib/oauth/code_response_spec.rb +1 -1
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +0 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +8 -11
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +22 -13
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +53 -6
- data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
- data/spec/lib/oauth/refresh_token_request_spec.rb +22 -14
- data/spec/lib/oauth/scopes_spec.rb +0 -3
- data/spec/lib/oauth/token_request_spec.rb +8 -9
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +40 -14
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +7 -7
- data/spec/lib/stale_records_cleaner_spec.rb +89 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
- data/spec/models/doorkeeper/access_token_spec.rb +80 -32
- data/spec/models/doorkeeper/application_spec.rb +293 -221
- data/spec/requests/applications/applications_request_spec.rb +134 -1
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +3 -3
- data/spec/requests/endpoints/token_spec.rb +7 -5
- data/spec/requests/flows/authorization_code_errors_spec.rb +2 -2
- data/spec/requests/flows/authorization_code_spec.rb +258 -2
- data/spec/requests/flows/client_credentials_spec.rb +46 -6
- data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +61 -3
- data/spec/requests/flows/refresh_token_spec.rb +59 -2
- data/spec/requests/flows/revoke_token_spec.rb +20 -20
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +3 -3
- data/spec/routing/custom_controller_routes_spec.rb +59 -7
- data/spec/routing/default_routes_spec.rb +2 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -74
- data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
- data/spec/support/doorkeeper_rspec.rb +20 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +8 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -2
- data/spec/support/helpers/url_helper.rb +18 -14
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/support/shared/controllers_shared_context.rb +56 -0
- data/spec/validators/redirect_uri_validator_spec.rb +9 -3
- data/spec/version/version_spec.rb +3 -3
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +54 -35
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
- data/spec/controllers/application_metal_controller.rb +0 -10
@@ -1,302 +1,374 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
describe Application do
|
5
|
-
let(:require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', true) }
|
6
|
-
let(:unset_require_owner) { Doorkeeper.configuration.instance_variable_set('@confirm_application_owner', false) }
|
7
|
-
let(:new_application) { FactoryBot.build(:application) }
|
3
|
+
require "spec_helper"
|
8
4
|
|
9
|
-
|
10
|
-
|
5
|
+
describe Doorkeeper::Application do
|
6
|
+
let(:require_owner) { Doorkeeper.configuration.instance_variable_set("@confirm_application_owner", true) }
|
7
|
+
let(:unset_require_owner) { Doorkeeper.configuration.instance_variable_set("@confirm_application_owner", false) }
|
8
|
+
let(:new_application) { FactoryBot.build(:application) }
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
Doorkeeper.configure do
|
15
|
-
orm DOORKEEPER_ORM
|
16
|
-
enable_application_owner
|
17
|
-
end
|
18
|
-
end
|
10
|
+
let(:uid) { SecureRandom.hex(8) }
|
11
|
+
let(:secret) { SecureRandom.hex(8) }
|
19
12
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
it "is invalid without a name" do
|
14
|
+
new_application.name = nil
|
15
|
+
expect(new_application).not_to be_valid
|
16
|
+
end
|
24
17
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
18
|
+
it "is invalid without determining confidentiality" do
|
19
|
+
new_application.confidential = nil
|
20
|
+
expect(new_application).not_to be_valid
|
21
|
+
end
|
29
22
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
it "generates uid on create" do
|
24
|
+
expect(new_application.uid).to be_nil
|
25
|
+
new_application.save
|
26
|
+
expect(new_application.uid).not_to be_nil
|
27
|
+
end
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
|
29
|
+
it "generates uid on create if an empty string" do
|
30
|
+
new_application.uid = ""
|
31
|
+
new_application.save
|
32
|
+
expect(new_application.uid).not_to be_blank
|
33
|
+
end
|
39
34
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
35
|
+
it "generates uid on create unless one is set" do
|
36
|
+
new_application.uid = uid
|
37
|
+
new_application.save
|
38
|
+
expect(new_application.uid).to eq(uid)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "is invalid without uid" do
|
42
|
+
new_application.save
|
43
|
+
new_application.uid = nil
|
44
|
+
expect(new_application).not_to be_valid
|
45
|
+
end
|
46
|
+
|
47
|
+
it "checks uniqueness of uid" do
|
48
|
+
app1 = FactoryBot.create(:application)
|
49
|
+
app2 = FactoryBot.create(:application)
|
50
|
+
app2.uid = app1.uid
|
51
|
+
expect(app2).not_to be_valid
|
52
|
+
end
|
53
|
+
|
54
|
+
it "expects database to throw an error when uids are the same" do
|
55
|
+
app1 = FactoryBot.create(:application)
|
56
|
+
app2 = FactoryBot.create(:application)
|
57
|
+
app2.uid = app1.uid
|
58
|
+
expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "generate secret on create" do
|
62
|
+
expect(new_application.secret).to be_nil
|
63
|
+
new_application.save
|
64
|
+
expect(new_application.secret).not_to be_nil
|
65
|
+
end
|
66
|
+
|
67
|
+
it "generate secret on create if is blank string" do
|
68
|
+
new_application.secret = ""
|
69
|
+
new_application.save
|
70
|
+
expect(new_application.secret).not_to be_blank
|
71
|
+
end
|
72
|
+
|
73
|
+
it "generate secret on create unless one is set" do
|
74
|
+
new_application.secret = secret
|
75
|
+
new_application.save
|
76
|
+
expect(new_application.secret).to eq(secret)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "is invalid without secret" do
|
80
|
+
new_application.save
|
81
|
+
new_application.secret = nil
|
82
|
+
expect(new_application).not_to be_valid
|
83
|
+
end
|
84
|
+
|
85
|
+
context "application_owner is enabled" do
|
86
|
+
before do
|
87
|
+
Doorkeeper.configure do
|
88
|
+
orm DOORKEEPER_ORM
|
89
|
+
enable_application_owner
|
44
90
|
end
|
45
91
|
end
|
46
92
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
93
|
+
context "application owner is not required" do
|
94
|
+
before(:each) do
|
95
|
+
unset_require_owner
|
96
|
+
end
|
51
97
|
|
52
|
-
|
53
|
-
|
54
|
-
|
98
|
+
it "is valid given valid attributes" do
|
99
|
+
expect(new_application).to be_valid
|
100
|
+
end
|
55
101
|
end
|
56
102
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
103
|
+
context "application owner is required" do
|
104
|
+
before do
|
105
|
+
require_owner
|
106
|
+
@owner = FactoryBot.build_stubbed(:doorkeeper_testing_user)
|
107
|
+
end
|
62
108
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
expect(new_application.uid).not_to be_blank
|
67
|
-
end
|
109
|
+
it "is invalid without an owner" do
|
110
|
+
expect(new_application).not_to be_valid
|
111
|
+
end
|
68
112
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
113
|
+
it "is valid with an owner" do
|
114
|
+
new_application.owner = @owner
|
115
|
+
expect(new_application).to be_valid
|
116
|
+
end
|
73
117
|
end
|
118
|
+
end
|
74
119
|
|
75
|
-
|
120
|
+
context "redirect URI" do
|
121
|
+
it "is invalid without redirect_uri" do
|
76
122
|
new_application.save
|
77
|
-
new_application.
|
123
|
+
new_application.redirect_uri = nil
|
78
124
|
expect(new_application).not_to be_valid
|
79
125
|
end
|
126
|
+
end
|
80
127
|
|
81
|
-
|
128
|
+
describe "destroy related models on cascade" do
|
129
|
+
before(:each) do
|
82
130
|
new_application.save
|
83
|
-
new_application.redirect_uri = nil
|
84
|
-
expect(new_application).not_to be_valid
|
85
131
|
end
|
86
132
|
|
87
|
-
|
88
|
-
app1 = FactoryBot.create(:application)
|
89
|
-
app2 = FactoryBot.create(:application)
|
90
|
-
app2.uid = app1.uid
|
91
|
-
expect(app2).not_to be_valid
|
92
|
-
end
|
133
|
+
let(:resource_owner) { FactoryBot.create(:doorkeeper_testing_user) }
|
93
134
|
|
94
|
-
it
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
135
|
+
it "should destroy its access grants" do
|
136
|
+
FactoryBot.create(
|
137
|
+
:access_grant,
|
138
|
+
application: new_application,
|
139
|
+
resource_owner_id: resource_owner.id,
|
140
|
+
)
|
100
141
|
|
101
|
-
|
102
|
-
expect(new_application.secret).to be_nil
|
103
|
-
new_application.save
|
104
|
-
expect(new_application.secret).not_to be_nil
|
142
|
+
expect { new_application.destroy }.to change { Doorkeeper::AccessGrant.count }.by(-1)
|
105
143
|
end
|
106
144
|
|
107
|
-
it
|
108
|
-
|
109
|
-
new_application.
|
110
|
-
expect
|
145
|
+
it "should destroy its access tokens" do
|
146
|
+
FactoryBot.create(:access_token, application: new_application)
|
147
|
+
FactoryBot.create(:access_token, application: new_application, revoked_at: Time.now.utc)
|
148
|
+
expect do
|
149
|
+
new_application.destroy
|
150
|
+
end.to change { Doorkeeper::AccessToken.count }.by(-2)
|
111
151
|
end
|
152
|
+
end
|
112
153
|
|
113
|
-
|
114
|
-
|
115
|
-
new_application.save
|
116
|
-
expect(new_application.secret).to eq(secret)
|
117
|
-
end
|
154
|
+
describe "#ordered_by" do
|
155
|
+
let(:applications) { FactoryBot.create_list(:application, 5) }
|
118
156
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
157
|
+
context "when a direction is not specified" do
|
158
|
+
it "calls order with a default order of asc" do
|
159
|
+
names = applications.map(&:name).sort
|
160
|
+
expect(described_class.ordered_by(:name).map(&:name)).to eq(names)
|
161
|
+
end
|
123
162
|
end
|
124
163
|
|
125
|
-
|
126
|
-
|
127
|
-
|
164
|
+
context "when a direction is specified" do
|
165
|
+
it "calls order with specified direction" do
|
166
|
+
names = applications.map(&:name).sort.reverse
|
167
|
+
expect(described_class.ordered_by(:name, :desc).map(&:name)).to eq(names)
|
128
168
|
end
|
169
|
+
end
|
170
|
+
end
|
129
171
|
|
130
|
-
|
131
|
-
|
132
|
-
|
172
|
+
describe "#redirect_uri=" do
|
173
|
+
context "when array of valid redirect_uris" do
|
174
|
+
it "should join by newline" do
|
175
|
+
new_application.redirect_uri = ["http://localhost/callback1", "http://localhost/callback2"]
|
176
|
+
expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
|
133
177
|
end
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
expect
|
139
|
-
new_application.destroy
|
140
|
-
end.to change { Doorkeeper::AccessToken.count }.by(-2)
|
178
|
+
end
|
179
|
+
context "when string of valid redirect_uris" do
|
180
|
+
it "should store as-is" do
|
181
|
+
new_application.redirect_uri = "http://localhost/callback1\nhttp://localhost/callback2"
|
182
|
+
expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
|
141
183
|
end
|
142
184
|
end
|
185
|
+
end
|
143
186
|
|
144
|
-
|
145
|
-
|
187
|
+
describe "#authorized_for" do
|
188
|
+
let(:resource_owner) { FactoryBot.create(:doorkeeper_testing_user) }
|
189
|
+
let(:other_resource_owner) { FactoryBot.create(:doorkeeper_testing_user) }
|
146
190
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
expect(Application.ordered_by(:name).map(&:name)).to eq(names)
|
151
|
-
end
|
152
|
-
end
|
191
|
+
it "is empty if the application is not authorized for anyone" do
|
192
|
+
expect(described_class.authorized_for(resource_owner)).to be_empty
|
193
|
+
end
|
153
194
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
195
|
+
it "returns only application for a specific resource owner" do
|
196
|
+
FactoryBot.create(
|
197
|
+
:access_token,
|
198
|
+
resource_owner_id: other_resource_owner.id,
|
199
|
+
)
|
200
|
+
token = FactoryBot.create(
|
201
|
+
:access_token,
|
202
|
+
resource_owner_id: resource_owner.id,
|
203
|
+
)
|
204
|
+
expect(described_class.authorized_for(resource_owner)).to eq([token.application])
|
160
205
|
end
|
161
206
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
context "when string of valid redirect_uris" do
|
170
|
-
it "should store as-is" do
|
171
|
-
new_application.redirect_uri = "http://localhost/callback1\nhttp://localhost/callback2"
|
172
|
-
expect(new_application.redirect_uri).to eq("http://localhost/callback1\nhttp://localhost/callback2")
|
173
|
-
end
|
174
|
-
end
|
207
|
+
it "excludes revoked tokens" do
|
208
|
+
FactoryBot.create(
|
209
|
+
:access_token,
|
210
|
+
resource_owner_id: resource_owner.id,
|
211
|
+
revoked_at: 2.days.ago,
|
212
|
+
)
|
213
|
+
expect(described_class.authorized_for(resource_owner)).to be_empty
|
175
214
|
end
|
176
215
|
|
177
|
-
|
178
|
-
|
216
|
+
it "returns all applications that have been authorized" do
|
217
|
+
token1 = FactoryBot.create(
|
218
|
+
:access_token,
|
219
|
+
resource_owner_id: resource_owner.id,
|
220
|
+
)
|
221
|
+
token2 = FactoryBot.create(
|
222
|
+
:access_token,
|
223
|
+
resource_owner_id: resource_owner.id,
|
224
|
+
)
|
225
|
+
expect(described_class.authorized_for(resource_owner))
|
226
|
+
.to eq([token1.application, token2.application])
|
227
|
+
end
|
179
228
|
|
180
|
-
|
181
|
-
|
182
|
-
|
229
|
+
it "returns only one application even if it has been authorized twice" do
|
230
|
+
application = FactoryBot.create(:application)
|
231
|
+
FactoryBot.create(
|
232
|
+
:access_token,
|
233
|
+
resource_owner_id: resource_owner.id,
|
234
|
+
application: application,
|
235
|
+
)
|
236
|
+
FactoryBot.create(
|
237
|
+
:access_token,
|
238
|
+
resource_owner_id: resource_owner.id,
|
239
|
+
application: application,
|
240
|
+
)
|
241
|
+
expect(described_class.authorized_for(resource_owner)).to eq([application])
|
242
|
+
end
|
243
|
+
end
|
183
244
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
245
|
+
describe "#revoke_tokens_and_grants_for" do
|
246
|
+
it "revokes all access tokens and access grants" do
|
247
|
+
application_id = 42
|
248
|
+
resource_owner = double
|
249
|
+
expect(Doorkeeper::AccessToken)
|
250
|
+
.to receive(:revoke_all_for).with(application_id, resource_owner)
|
251
|
+
expect(Doorkeeper::AccessGrant)
|
252
|
+
.to receive(:revoke_all_for).with(application_id, resource_owner)
|
189
253
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
254
|
+
described_class.revoke_tokens_and_grants_for(application_id, resource_owner)
|
255
|
+
end
|
256
|
+
end
|
194
257
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
258
|
+
describe "#by_uid_and_secret" do
|
259
|
+
context "when application is private/confidential" do
|
260
|
+
it "finds the application via uid/secret" do
|
261
|
+
app = FactoryBot.create :application
|
262
|
+
authenticated = described_class.by_uid_and_secret(app.uid, app.secret)
|
263
|
+
expect(authenticated).to eq(app)
|
199
264
|
end
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
265
|
+
context "when secret is wrong" do
|
266
|
+
it "should not find the application" do
|
267
|
+
app = FactoryBot.create :application
|
268
|
+
authenticated = described_class.by_uid_and_secret(app.uid, "bad")
|
269
|
+
expect(authenticated).to eq(nil)
|
270
|
+
end
|
206
271
|
end
|
207
272
|
end
|
208
273
|
|
209
|
-
|
210
|
-
context "when
|
211
|
-
it "
|
212
|
-
app = FactoryBot.create :application
|
213
|
-
authenticated =
|
274
|
+
context "when application is public/non-confidential" do
|
275
|
+
context "when secret is blank" do
|
276
|
+
it "should find the application" do
|
277
|
+
app = FactoryBot.create :application, confidential: false
|
278
|
+
authenticated = described_class.by_uid_and_secret(app.uid, nil)
|
214
279
|
expect(authenticated).to eq(app)
|
215
280
|
end
|
216
|
-
context "when secret is wrong" do
|
217
|
-
it "should not find the application" do
|
218
|
-
app = FactoryBot.create :application
|
219
|
-
authenticated = Application.by_uid_and_secret(app.uid, 'bad')
|
220
|
-
expect(authenticated).to eq(nil)
|
221
|
-
end
|
222
|
-
end
|
223
281
|
end
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
authenticated = Application.by_uid_and_secret(app.uid, nil)
|
230
|
-
expect(authenticated).to eq(app)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
context "when secret is wrong" do
|
234
|
-
it "should not find the application" do
|
235
|
-
app = FactoryBot.create :application, confidential: false
|
236
|
-
authenticated = Application.by_uid_and_secret(app.uid, 'bad')
|
237
|
-
expect(authenticated).to eq(nil)
|
238
|
-
end
|
282
|
+
context "when secret is wrong" do
|
283
|
+
it "should not find the application" do
|
284
|
+
app = FactoryBot.create :application, confidential: false
|
285
|
+
authenticated = described_class.by_uid_and_secret(app.uid, "bad")
|
286
|
+
expect(authenticated).to eq(nil)
|
239
287
|
end
|
240
288
|
end
|
241
289
|
end
|
290
|
+
end
|
242
291
|
|
243
|
-
|
244
|
-
|
292
|
+
describe "#confidential?" do
|
293
|
+
subject { FactoryBot.create(:application, confidential: confidential).confidential? }
|
245
294
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
295
|
+
context "when application is private/confidential" do
|
296
|
+
let(:confidential) { true }
|
297
|
+
it { expect(subject).to eq(true) }
|
298
|
+
end
|
250
299
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
end
|
300
|
+
context "when application is public/non-confidential" do
|
301
|
+
let(:confidential) { false }
|
302
|
+
it { expect(subject).to eq(false) }
|
255
303
|
end
|
304
|
+
end
|
256
305
|
|
257
|
-
|
258
|
-
|
306
|
+
describe "#as_json" do
|
307
|
+
let(:app) { FactoryBot.create :application, secret: "123123123" }
|
259
308
|
|
260
|
-
|
261
|
-
|
262
|
-
|
309
|
+
# AR specific feature
|
310
|
+
if DOORKEEPER_ORM == :active_record
|
311
|
+
it "correctly works with #to_json" do
|
312
|
+
ActiveRecord::Base.include_root_in_json = true
|
313
|
+
expect(app.to_json(include_root_in_json: true)).to match(/application.+?:\{/)
|
314
|
+
ActiveRecord::Base.include_root_in_json = false
|
263
315
|
end
|
316
|
+
end
|
264
317
|
|
265
|
-
|
266
|
-
|
267
|
-
|
318
|
+
context "when called without authorized resource owner" do
|
319
|
+
it "includes minimal set of attributes" do
|
320
|
+
expect(app.as_json).to match(
|
321
|
+
"id" => app.id,
|
322
|
+
"name" => app.name,
|
323
|
+
"created_at" => anything,
|
324
|
+
)
|
268
325
|
end
|
269
326
|
|
270
|
-
|
271
|
-
|
327
|
+
it "includes application UID if it's public" do
|
328
|
+
app = FactoryBot.create :application, secret: "123123123", confidential: false
|
272
329
|
|
273
|
-
|
330
|
+
expect(app.as_json).to match(
|
331
|
+
"id" => app.id,
|
332
|
+
"name" => app.name,
|
333
|
+
"created_at" => anything,
|
334
|
+
"uid" => app.uid,
|
335
|
+
)
|
336
|
+
end
|
274
337
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
338
|
+
it "respects custom options" do
|
339
|
+
expect(app.as_json(except: :id)).not_to include("id")
|
340
|
+
expect(app.as_json(only: %i[name created_at secret]))
|
341
|
+
.to match(
|
342
|
+
"name" => app.name,
|
343
|
+
"created_at" => anything,
|
280
344
|
)
|
281
|
-
Application.new.confidential
|
282
|
-
end
|
283
|
-
|
284
|
-
it { expect(subject).to eq(true) }
|
285
345
|
end
|
286
346
|
end
|
287
347
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
348
|
+
context "when called with authorized resource owner" do
|
349
|
+
let(:owner) { FactoryBot.create(:doorkeeper_testing_user) }
|
350
|
+
let(:other_owner) { FactoryBot.create(:doorkeeper_testing_user) }
|
351
|
+
let(:app) { FactoryBot.create(:application, secret: "123123123", owner: owner) }
|
352
|
+
|
353
|
+
before do
|
354
|
+
Doorkeeper.configure do
|
355
|
+
orm DOORKEEPER_ORM
|
356
|
+
enable_application_owner confirmation: false
|
293
357
|
end
|
294
358
|
end
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
359
|
+
|
360
|
+
it "includes all the attributes" do
|
361
|
+
expect(app.as_json(current_resource_owner: owner))
|
362
|
+
.to include(
|
363
|
+
"secret" => "123123123",
|
364
|
+
"redirect_uri" => app.redirect_uri,
|
365
|
+
"uid" => app.uid,
|
366
|
+
)
|
367
|
+
end
|
368
|
+
|
369
|
+
it "doesn't include unsafe attributes if current owner isn't the same as owner" do
|
370
|
+
expect(app.as_json(current_resource_owner: other_owner))
|
371
|
+
.not_to include("redirect_uri")
|
300
372
|
end
|
301
373
|
end
|
302
374
|
end
|