doorkeeper-mongodb 5.2.1 → 5.2.2
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/lib/doorkeeper-mongodb.rb +1 -0
- data/lib/doorkeeper-mongodb/mixins/mongoid/access_grant_mixin.rb +1 -0
- data/lib/doorkeeper-mongodb/mixins/mongoid/access_token_mixin.rb +1 -0
- data/lib/doorkeeper-mongodb/mixins/mongoid/application_mixin.rb +76 -0
- data/lib/doorkeeper-mongodb/mixins/mongoid/base_mixin.rb +0 -8
- data/lib/doorkeeper-mongodb/mixins/mongoid/json_serializable.rb +17 -0
- data/lib/doorkeeper-mongodb/version.rb +1 -1
- data/spec/controllers/application_metal_controller_spec.rb +4 -4
- data/spec/controllers/applications_controller_spec.rb +198 -202
- data/spec/controllers/authorizations_controller_spec.rb +32 -31
- data/spec/controllers/protected_resources_controller_spec.rb +10 -10
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +105 -62
- data/spec/doorkeeper/redirect_uri_validator_spec.rb +183 -0
- data/spec/{lib → doorkeeper}/server_spec.rb +5 -4
- data/spec/{lib → doorkeeper}/stale_records_cleaner_spec.rb +8 -7
- data/spec/{version → doorkeeper}/version_spec.rb +3 -3
- data/spec/dummy/log/test.log +4220 -4184
- data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{eS/eSL1QMz46gKLM0GR6S9fL6uyARPxOImcappZ9_ZtSyg.cache → Pm/PmheG0PGFqDws1qgFOxOyIL-gpMof3Ar9eSRKVLYuik.cache} +0 -0
- data/spec/grape/grape_integration_spec.rb +1 -1
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +23 -12
- data/spec/lib/doorkeeper_spec.rb +4 -4
- data/spec/lib/models/expirable_spec.rb +9 -9
- data/spec/lib/models/reusable_spec.rb +2 -2
- data/spec/lib/models/revocable_spec.rb +4 -7
- data/spec/lib/models/scopes_spec.rb +7 -7
- data/spec/lib/models/secret_storable_spec.rb +9 -8
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +23 -27
- data/spec/lib/oauth/authorization_code_request_spec.rb +6 -6
- data/spec/lib/oauth/base_request_spec.rb +11 -27
- data/spec/lib/oauth/base_response_spec.rb +2 -2
- data/spec/lib/oauth/client/credentials_spec.rb +25 -25
- data/spec/lib/oauth/client_credentials/creator_spec.rb +89 -91
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +84 -86
- data/spec/lib/oauth/client_credentials/validation_spec.rb +72 -39
- data/spec/lib/oauth/client_credentials_integration_spec.rb +5 -5
- data/spec/lib/oauth/client_credentials_request_spec.rb +7 -10
- data/spec/lib/oauth/client_spec.rb +8 -8
- data/spec/lib/oauth/code_request_spec.rb +5 -5
- data/spec/lib/oauth/code_response_spec.rb +4 -4
- data/spec/lib/oauth/error_response_spec.rb +6 -5
- data/spec/lib/oauth/error_spec.rb +1 -1
- data/spec/lib/oauth/forbidden_token_response_spec.rb +2 -2
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +37 -37
- data/spec/lib/oauth/helpers/unique_token_spec.rb +2 -2
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +54 -54
- data/spec/lib/oauth/invalid_request_response_spec.rb +6 -6
- data/spec/lib/oauth/invalid_token_response_spec.rb +4 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +10 -9
- data/spec/lib/oauth/pre_authorization_spec.rb +20 -8
- data/spec/lib/oauth/refresh_token_request_spec.rb +10 -10
- data/spec/lib/oauth/scopes_spec.rb +14 -14
- data/spec/lib/oauth/token_request_spec.rb +9 -9
- data/spec/lib/oauth/token_response_spec.rb +5 -5
- data/spec/lib/oauth/token_spec.rb +5 -5
- data/spec/lib/option_spec.rb +1 -1
- data/spec/lib/request/strategy_spec.rb +34 -37
- data/spec/lib/secret_storing/base_spec.rb +3 -2
- data/spec/lib/secret_storing/bcrypt_spec.rb +2 -1
- data/spec/lib/secret_storing/plain_spec.rb +2 -1
- data/spec/lib/secret_storing/sha256_hash_spec.rb +2 -1
- data/spec/models/doorkeeper/access_grant_spec.rb +7 -9
- data/spec/models/doorkeeper/access_token_spec.rb +20 -26
- data/spec/models/doorkeeper/application_spec.rb +83 -26
- data/spec/requests/applications/applications_request_spec.rb +91 -93
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +22 -16
- data/spec/requests/flows/authorization_code_errors_spec.rb +12 -8
- data/spec/requests/flows/authorization_code_spec.rb +108 -79
- data/spec/requests/flows/client_credentials_spec.rb +57 -45
- data/spec/requests/flows/implicit_grant_spec.rb +4 -4
- data/spec/requests/flows/password_spec.rb +253 -213
- data/spec/requests/flows/refresh_token_spec.rb +53 -39
- data/spec/requests/flows/revoke_token_spec.rb +24 -24
- data/spec/requests/flows/skip_authorization_spec.rb +1 -1
- data/spec/requests/protected_resources/metal_spec.rb +2 -2
- data/spec/routing/custom_controller_routes_spec.rb +1 -1
- data/spec/routing/default_routes_spec.rb +1 -1
- data/spec/routing/scoped_routes_spec.rb +1 -1
- data/spec/support/helpers/request_spec_helper.rb +1 -13
- data/spec/support/helpers/url_helper.rb +2 -2
- data/spec/support/shared/controllers_shared_context.rb +5 -38
- data/spec/support/shared/hashing_shared_context.rb +4 -0
- data/spec/support/shared/models_shared_examples.rb +6 -6
- metadata +13 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6ca032c54f4098b2652bde530b4cc204b124d76e5d066ddd04d302302dd854b7
|
|
4
|
+
data.tar.gz: 24fe8d9ad134bcd6eba2b8f9ae8e76b956d0e5eabe527ecece33c8ed51211049
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3ff745bcac86d2cc5c10d8e7548c487fce3626e9570da0f66e1fc47de25bf5f5b323dd650512b14b4e248567e278a66707a1d2af52e0e15f5d9f14af9eda68e8
|
|
7
|
+
data.tar.gz: 7cdb26333c287aa9731561a4b9e59dd9115a1205be92e6e1a4e2686bcfb5d5d67b77609ec3aeff94a00dc2f96decce40ce7f55d748cc461c709b35a4fa6cedee
|
data/lib/doorkeeper-mongodb.rb
CHANGED
|
@@ -17,6 +17,7 @@ require "doorkeeper/orm/concerns/mongoid/ownership"
|
|
|
17
17
|
require "doorkeeper/orm/concerns/mongoid/resource_ownerable"
|
|
18
18
|
|
|
19
19
|
require "doorkeeper-mongodb/mixins/mongoid/base_mixin"
|
|
20
|
+
require "doorkeeper-mongodb/mixins/mongoid/json_serializable"
|
|
20
21
|
require "doorkeeper-mongodb/mixins/mongoid/access_grant_mixin"
|
|
21
22
|
require "doorkeeper-mongodb/mixins/mongoid/access_token_mixin"
|
|
22
23
|
require "doorkeeper-mongodb/mixins/mongoid/application_mixin"
|
|
@@ -51,6 +51,82 @@ module DoorkeeperMongodb
|
|
|
51
51
|
validate :scopes_match_configured, if: :enforce_scopes?
|
|
52
52
|
|
|
53
53
|
before_validation :generate_uid, :generate_secret, on: :create
|
|
54
|
+
|
|
55
|
+
# Represents client as set of it's attributes in JSON format.
|
|
56
|
+
# This is the right way how we want to override ActiveRecord #to_json.
|
|
57
|
+
#
|
|
58
|
+
# Respects privacy settings and serializes minimum set of attributes
|
|
59
|
+
# for public/private clients and full set for authorized owners.
|
|
60
|
+
#
|
|
61
|
+
# @return [Hash] entity attributes for JSON
|
|
62
|
+
#
|
|
63
|
+
def as_json(options = {})
|
|
64
|
+
# if application belongs to some owner we need to check if it's the same as
|
|
65
|
+
# the one passed in the options or check if we render the client as an owner
|
|
66
|
+
if (respond_to?(:owner) && owner && owner == options[:current_resource_owner]) ||
|
|
67
|
+
options[:as_owner]
|
|
68
|
+
# Owners can see all the client attributes, fallback to ActiveModel serialization
|
|
69
|
+
super
|
|
70
|
+
else
|
|
71
|
+
# if application has no owner or it's owner doesn't match one from the options
|
|
72
|
+
# we render only minimum set of attributes that could be exposed to a public
|
|
73
|
+
only = extract_serializable_attributes(options)
|
|
74
|
+
super(options.merge(only: only))
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def serializable_hash(options = nil)
|
|
79
|
+
hash = super
|
|
80
|
+
if hash.key?("_id")
|
|
81
|
+
hash["id"] = hash.delete("_id")
|
|
82
|
+
elsif options && Array.wrap(options[:only].map(&:to_sym)).include?(:id)
|
|
83
|
+
hash["id"] = id.to_s
|
|
84
|
+
end
|
|
85
|
+
hash
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Helper method to extract collection of serializable attribute names
|
|
89
|
+
# considering serialization options (like `only`, `except` and so on).
|
|
90
|
+
#
|
|
91
|
+
# @param options [Hash] serialization options
|
|
92
|
+
#
|
|
93
|
+
# @return [Array<String>]
|
|
94
|
+
# collection of attributes to be serialized using #as_json
|
|
95
|
+
#
|
|
96
|
+
def extract_serializable_attributes(options = {})
|
|
97
|
+
opts = options.try(:dup) || {}
|
|
98
|
+
only = Array.wrap(opts[:only]).map(&:to_s)
|
|
99
|
+
|
|
100
|
+
only = if only.blank?
|
|
101
|
+
serializable_attributes
|
|
102
|
+
else
|
|
103
|
+
only & serializable_attributes
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
|
|
107
|
+
only.uniq
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# We need to hook into this method to allow serializing plan-text secrets
|
|
111
|
+
# when secrets hashing enabled.
|
|
112
|
+
#
|
|
113
|
+
# @param key [String] attribute name
|
|
114
|
+
#
|
|
115
|
+
def read_attribute_for_serialization(key)
|
|
116
|
+
return super unless key.to_s == "secret"
|
|
117
|
+
|
|
118
|
+
plaintext_secret || secret
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Collection of attributes that could be serialized for public.
|
|
122
|
+
# Override this method if you need additional attributes to be serialized.
|
|
123
|
+
#
|
|
124
|
+
# @return [Array<String>] collection of serializable attributes
|
|
125
|
+
def serializable_attributes
|
|
126
|
+
attributes = %w[id name created_at]
|
|
127
|
+
attributes << "uid" unless confidential?
|
|
128
|
+
attributes
|
|
129
|
+
end
|
|
54
130
|
end
|
|
55
131
|
|
|
56
132
|
module ClassMethods
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DoorkeeperMongodb
|
|
4
|
+
module Mixins
|
|
5
|
+
module Mongoid
|
|
6
|
+
module JsonSerializable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
def as_json(*args)
|
|
10
|
+
json = super
|
|
11
|
+
json["id"] = json.delete("_id") if json.key?("_id")
|
|
12
|
+
json
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "spec_helper_integration"
|
|
4
4
|
|
|
5
|
-
describe Doorkeeper::ApplicationMetalController do
|
|
6
|
-
controller(
|
|
5
|
+
RSpec.describe Doorkeeper::ApplicationMetalController do
|
|
6
|
+
controller(described_class) do
|
|
7
7
|
def index
|
|
8
8
|
render json: {}, status: 200
|
|
9
9
|
end
|
|
@@ -23,7 +23,7 @@ describe Doorkeeper::ApplicationMetalController do
|
|
|
23
23
|
describe "enforce_content_type" do
|
|
24
24
|
before { allow(Doorkeeper.config).to receive(:enforce_content_type).and_return(flag) }
|
|
25
25
|
|
|
26
|
-
context "enabled" do
|
|
26
|
+
context "when enabled" do
|
|
27
27
|
let(:flag) { true }
|
|
28
28
|
|
|
29
29
|
it "returns a 200 for the requests without body" do
|
|
@@ -42,7 +42,7 @@ describe Doorkeeper::ApplicationMetalController do
|
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
context "disabled" do
|
|
45
|
+
context "when disabled" do
|
|
46
46
|
let(:flag) { false }
|
|
47
47
|
|
|
48
48
|
it "returns a 200 for the correct media type" do
|
|
@@ -2,132 +2,154 @@
|
|
|
2
2
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
context "JSON API" do
|
|
8
|
-
render_views
|
|
5
|
+
RSpec.describe Doorkeeper::ApplicationsController do
|
|
6
|
+
render_views
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
context "when JSON API used" do
|
|
9
|
+
before do
|
|
10
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
11
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
|
|
12
|
+
end
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
it "creates an application" do
|
|
15
|
+
expect do
|
|
16
|
+
post :create, params: {
|
|
17
|
+
doorkeeper_application: {
|
|
18
|
+
name: "Example",
|
|
19
|
+
redirect_uri: "https://example.com",
|
|
20
|
+
}, format: :json,
|
|
21
|
+
}
|
|
22
|
+
end.to(change { Doorkeeper::Application.count })
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
expect(response).to be_successful
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
application = Doorkeeper::Application.last
|
|
29
|
+
secret_from_response = json_response["secret"]
|
|
30
|
+
expect(application).to be_secret_matches(secret_from_response)
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
expect(json_response["name"]).to eq("Example")
|
|
33
|
+
expect(json_response["redirect_uri"]).to eq("https://example.com")
|
|
34
|
+
end
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
it "returns validation errors on wrong create params" do
|
|
37
|
+
expect do
|
|
38
|
+
post :create, params: {
|
|
39
|
+
doorkeeper_application: {
|
|
40
|
+
name: "Example",
|
|
41
|
+
}, format: :json,
|
|
42
|
+
}
|
|
43
|
+
end.not_to(change { Doorkeeper::Application.count })
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
expect(response).to have_http_status(422)
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
expect(json_response).to include("errors")
|
|
48
|
+
end
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
it "returns validations on wrong create params (unspecified scheme)" do
|
|
51
|
+
expect do
|
|
52
|
+
post :create, params: {
|
|
53
|
+
doorkeeper_application: {
|
|
54
|
+
name: "Example",
|
|
55
|
+
redirect_uri: "app.com:80",
|
|
56
|
+
}, format: :json,
|
|
57
|
+
}
|
|
58
|
+
end.not_to(change { Doorkeeper::Application.count })
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
expect(response).to have_http_status(422)
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
expect(json_response).to include("errors")
|
|
63
|
+
end
|
|
65
64
|
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
it "returns application info" do
|
|
66
|
+
application = FactoryBot.create(:application, name: "Change me")
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
get :show, params: { id: application.id, format: :json }
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
expect(response).to be_successful
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
|
|
73
|
+
end
|
|
75
74
|
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
it "updates application" do
|
|
76
|
+
application = FactoryBot.create(:application, name: "Change me")
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
78
|
+
put :update, params: {
|
|
79
|
+
id: application.id,
|
|
80
|
+
doorkeeper_application: {
|
|
81
|
+
name: "Example App",
|
|
82
|
+
redirect_uri: "https://example.com",
|
|
83
|
+
}, format: :json,
|
|
84
|
+
}
|
|
86
85
|
|
|
87
|
-
|
|
86
|
+
expect(application.reload.name).to eq "Example App"
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
|
|
89
|
+
end
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
it "returns validation errors on wrong update params" do
|
|
92
|
+
application = FactoryBot.create(:application, name: "Change me")
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
put :update, params: {
|
|
95
|
+
id: application.id,
|
|
96
|
+
doorkeeper_application: {
|
|
97
|
+
name: "Example App",
|
|
98
|
+
redirect_uri: "localhost:3000",
|
|
99
|
+
}, format: :json,
|
|
100
|
+
}
|
|
102
101
|
|
|
103
|
-
|
|
102
|
+
expect(response).to have_http_status(422)
|
|
104
103
|
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
expect(json_response).to include("errors")
|
|
105
|
+
end
|
|
107
106
|
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
it "destroys an application" do
|
|
108
|
+
application = FactoryBot.create(:application)
|
|
110
109
|
|
|
111
|
-
|
|
110
|
+
delete :destroy, params: { id: application.id, format: :json }
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
end
|
|
112
|
+
expect(response).to have_http_status(204)
|
|
113
|
+
expect(Doorkeeper::Application.count).to be_zero
|
|
116
114
|
end
|
|
115
|
+
end
|
|
117
116
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
context "when admin is not authenticated" do
|
|
118
|
+
before do
|
|
119
|
+
allow(Doorkeeper.config).to receive(:authenticate_admin).and_return(proc do
|
|
120
|
+
redirect_to main_app.root_url
|
|
121
|
+
end)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "redirects as set in Doorkeeper.authenticate_admin" do
|
|
125
|
+
get :index
|
|
126
|
+
expect(response).to redirect_to(controller.main_app.root_url)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "does not create application" do
|
|
130
|
+
expect do
|
|
131
|
+
post :create, params: {
|
|
132
|
+
doorkeeper_application: {
|
|
133
|
+
name: "Example",
|
|
134
|
+
redirect_uri: "https://example.com",
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
end.not_to(change { Doorkeeper::Application.count })
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context "when admin is authenticated" do
|
|
142
|
+
before do
|
|
143
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
|
|
144
|
+
end
|
|
124
145
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
146
|
+
context "when application secrets are hashed" do
|
|
147
|
+
before do
|
|
148
|
+
allow(Doorkeeper.configuration)
|
|
149
|
+
.to receive(:application_secret_strategy).and_return(Doorkeeper::SecretStoring::Sha256Hash)
|
|
128
150
|
end
|
|
129
151
|
|
|
130
|
-
it "
|
|
152
|
+
it "shows the application secret after creating a new application" do
|
|
131
153
|
expect do
|
|
132
154
|
post :create, params: {
|
|
133
155
|
doorkeeper_application: {
|
|
@@ -135,140 +157,114 @@ module Doorkeeper
|
|
|
135
157
|
redirect_uri: "https://example.com",
|
|
136
158
|
},
|
|
137
159
|
}
|
|
138
|
-
end.
|
|
139
|
-
end
|
|
140
|
-
end
|
|
160
|
+
end.to change { Doorkeeper::Application.count }.by(1)
|
|
141
161
|
|
|
142
|
-
|
|
143
|
-
context "when application secrets are hashed" do
|
|
144
|
-
before do
|
|
145
|
-
allow(Doorkeeper.configuration)
|
|
146
|
-
.to receive(:application_secret_strategy).and_return(Doorkeeper::SecretStoring::Sha256Hash)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
it "shows the application secret after creating a new application" do
|
|
150
|
-
expect do
|
|
151
|
-
post :create, params: {
|
|
152
|
-
doorkeeper_application: {
|
|
153
|
-
name: "Example",
|
|
154
|
-
redirect_uri: "https://example.com",
|
|
155
|
-
},
|
|
156
|
-
}
|
|
157
|
-
end.to change { Doorkeeper::Application.count }.by(1)
|
|
158
|
-
|
|
159
|
-
application = Application.last
|
|
160
|
-
|
|
161
|
-
secret_from_flash = flash[:application_secret]
|
|
162
|
-
expect(secret_from_flash).not_to be_empty
|
|
163
|
-
expect(application.secret_matches?(secret_from_flash)).to be_truthy
|
|
164
|
-
expect(response).to redirect_to(controller.main_app.oauth_application_url(application.id))
|
|
165
|
-
|
|
166
|
-
get :show, params: { id: application.id, format: :html }
|
|
167
|
-
|
|
168
|
-
# We don't know the application secret here (because its hashed) so we can not assert its text on the page
|
|
169
|
-
# Instead, we read it from the page and then check if it matches the application secret
|
|
170
|
-
code_element = %r{<code.*id="secret".*>(.*)<\/code>}.match(response.body)
|
|
171
|
-
secret_from_page = code_element[1]
|
|
172
|
-
|
|
173
|
-
expect(response.body).to have_selector("code#application_id", text: application.uid)
|
|
174
|
-
expect(response.body).to have_selector("code#secret")
|
|
175
|
-
expect(secret_from_page).not_to be_empty
|
|
176
|
-
expect(application.secret_matches?(secret_from_page)).to be_truthy
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
it "does not show an application secret when application did already exist" do
|
|
180
|
-
application = FactoryBot.create(:application)
|
|
181
|
-
get :show, params: { id: application.id, format: :html }
|
|
182
|
-
|
|
183
|
-
expect(response.body).to have_selector("code#application_id", text: application.uid)
|
|
184
|
-
expect(response.body).to have_selector("code#secret", text: "")
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
it "returns the application details in a json response" do
|
|
188
|
-
expect do
|
|
189
|
-
post :create, params: {
|
|
190
|
-
doorkeeper_application: {
|
|
191
|
-
name: "Example",
|
|
192
|
-
redirect_uri: "https://example.com",
|
|
193
|
-
}, format: :json,
|
|
194
|
-
}
|
|
195
|
-
end.to(change { Doorkeeper::Application.count })
|
|
196
|
-
|
|
197
|
-
expect(response).to be_successful
|
|
198
|
-
|
|
199
|
-
expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
|
|
200
|
-
|
|
201
|
-
application = Application.last
|
|
202
|
-
secret_from_response = json_response["secret"]
|
|
203
|
-
expect(application.secret_matches?(secret_from_response)).to be_truthy
|
|
204
|
-
|
|
205
|
-
expect(json_response["name"]).to eq("Example")
|
|
206
|
-
expect(json_response["redirect_uri"]).to eq("https://example.com")
|
|
207
|
-
end
|
|
208
|
-
end
|
|
162
|
+
application = Doorkeeper::Application.last
|
|
209
163
|
|
|
210
|
-
|
|
164
|
+
secret_from_flash = flash[:application_secret]
|
|
165
|
+
expect(secret_from_flash).not_to be_empty
|
|
166
|
+
expect(application).to be_secret_matches(secret_from_flash)
|
|
167
|
+
expect(response).to redirect_to(controller.main_app.oauth_application_url(application.id))
|
|
211
168
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
169
|
+
get :show, params: { id: application.id, format: :html }
|
|
170
|
+
|
|
171
|
+
# We don't know the application secret here (because its hashed) so we can not assert its text on the page
|
|
172
|
+
# Instead, we read it from the page and then check if it matches the application secret
|
|
173
|
+
code_element = /code.*id="secret">\s*\K([^<]*)/m.match(response.body)
|
|
174
|
+
secret_from_page = code_element[1].strip
|
|
215
175
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
expect(
|
|
176
|
+
expect(response.body).to have_selector("code#application_id", text: application.uid)
|
|
177
|
+
expect(response.body).to have_selector("code#secret")
|
|
178
|
+
expect(secret_from_page).not_to be_empty
|
|
179
|
+
expect(application).to be_secret_matches(secret_from_page)
|
|
180
|
+
end
|
|
220
181
|
|
|
221
|
-
|
|
182
|
+
it "does not show an application secret when application did already exist" do
|
|
183
|
+
application = FactoryBot.create(:application)
|
|
184
|
+
get :show, params: { id: application.id, format: :html }
|
|
222
185
|
|
|
223
|
-
expect(response.body).to have_selector("
|
|
224
|
-
expect(response.body).to have_selector("
|
|
186
|
+
expect(response.body).to have_selector("code#application_id", text: application.uid)
|
|
187
|
+
expect(response.body).to have_selector("code#secret", text: "")
|
|
225
188
|
end
|
|
226
189
|
|
|
227
|
-
it "
|
|
190
|
+
it "returns the application details in a json response" do
|
|
228
191
|
expect do
|
|
229
192
|
post :create, params: {
|
|
230
193
|
doorkeeper_application: {
|
|
231
194
|
name: "Example",
|
|
232
195
|
redirect_uri: "https://example.com",
|
|
233
|
-
},
|
|
196
|
+
}, format: :json,
|
|
234
197
|
}
|
|
235
|
-
end.to
|
|
198
|
+
end.to(change { Doorkeeper::Application.count })
|
|
236
199
|
|
|
237
|
-
expect(response).to
|
|
238
|
-
end
|
|
200
|
+
expect(response).to be_successful
|
|
239
201
|
|
|
240
|
-
|
|
241
|
-
application = FactoryBot.create(:application)
|
|
242
|
-
get :show, params: { id: application.id, format: :html }
|
|
202
|
+
expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
|
|
243
203
|
|
|
244
|
-
|
|
245
|
-
|
|
204
|
+
application = Doorkeeper::Application.last
|
|
205
|
+
secret_from_response = json_response["secret"]
|
|
206
|
+
expect(application).to be_secret_matches(secret_from_response)
|
|
207
|
+
|
|
208
|
+
expect(json_response["name"]).to eq("Example")
|
|
209
|
+
expect(json_response["redirect_uri"]).to eq("https://example.com")
|
|
246
210
|
end
|
|
211
|
+
end
|
|
247
212
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
doorkeeper_application: {
|
|
253
|
-
uid: "1A2B3C4D",
|
|
254
|
-
secret: "1A2B3C4D",
|
|
255
|
-
},
|
|
256
|
-
}
|
|
213
|
+
it "sorts applications by created_at" do
|
|
214
|
+
first_application = FactoryBot.create(:application)
|
|
215
|
+
second_application = FactoryBot.create(:application)
|
|
216
|
+
expect(Doorkeeper::Application).to receive(:ordered_by).and_call_original
|
|
257
217
|
|
|
258
|
-
|
|
259
|
-
end
|
|
218
|
+
get :index
|
|
260
219
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
220
|
+
expect(response.body).to have_selector("tbody tr:first-child#application_#{first_application.id}")
|
|
221
|
+
expect(response.body).to have_selector("tbody tr:last-child#application_#{second_application.id}")
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it "creates application" do
|
|
225
|
+
expect do
|
|
226
|
+
post :create, params: {
|
|
227
|
+
doorkeeper_application: {
|
|
265
228
|
name: "Example",
|
|
266
229
|
redirect_uri: "https://example.com",
|
|
267
230
|
},
|
|
268
231
|
}
|
|
232
|
+
end.to change { Doorkeeper::Application.count }.by(1)
|
|
269
233
|
|
|
270
|
-
|
|
271
|
-
|
|
234
|
+
expect(response).to be_redirect
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "shows application details" do
|
|
238
|
+
application = FactoryBot.create(:application)
|
|
239
|
+
get :show, params: { id: application.id, format: :html }
|
|
240
|
+
|
|
241
|
+
expect(response.body).to have_selector("code#application_id", text: application.uid)
|
|
242
|
+
expect(response.body).to have_selector("code#secret", text: application.plaintext_secret)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it "does not allow mass assignment of uid or secret" do
|
|
246
|
+
application = FactoryBot.create(:application)
|
|
247
|
+
put :update, params: {
|
|
248
|
+
id: application.id,
|
|
249
|
+
doorkeeper_application: {
|
|
250
|
+
uid: "1A2B3C4D",
|
|
251
|
+
secret: "1A2B3C4D",
|
|
252
|
+
},
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
expect(application.reload.uid).not_to eq "1A2B3C4D"
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "updates application" do
|
|
259
|
+
application = FactoryBot.create(:application)
|
|
260
|
+
put :update, params: {
|
|
261
|
+
id: application.id, doorkeeper_application: {
|
|
262
|
+
name: "Example",
|
|
263
|
+
redirect_uri: "https://example.com",
|
|
264
|
+
},
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
expect(application.reload.name).to eq "Example"
|
|
272
268
|
end
|
|
273
269
|
end
|
|
274
270
|
end
|