doorkeeper-mongodb 5.2.1 → 5.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|