keycloak-admin 2.0.1 → 2.0.3
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/CHANGELOG.md +40 -0
- data/MIT-LICENSE +18 -17
- data/README.md +102 -5
- data/keycloak-admin.gemspec +15 -6
- data/lib/keycloak-admin/client/attack_detection_client.rb +2 -1
- data/lib/keycloak-admin/client/client.rb +36 -11
- data/lib/keycloak-admin/client/client_authz_permission_client.rb +5 -4
- data/lib/keycloak-admin/client/client_authz_policy_client.rb +4 -3
- data/lib/keycloak-admin/client/client_authz_resource_client.rb +15 -11
- data/lib/keycloak-admin/client/client_authz_scope_client.rb +5 -4
- data/lib/keycloak-admin/client/client_client.rb +6 -2
- data/lib/keycloak-admin/client/client_role_client.rb +2 -1
- data/lib/keycloak-admin/client/client_role_mappings_client.rb +3 -2
- data/lib/keycloak-admin/client/client_scope_client.rb +2 -1
- data/lib/keycloak-admin/client/client_scope_protocol_mapper_client.rb +3 -2
- data/lib/keycloak-admin/client/configurable_token_client.rb +2 -1
- data/lib/keycloak-admin/client/group_client.rb +15 -9
- data/lib/keycloak-admin/client/identity_provider_client.rb +2 -1
- data/lib/keycloak-admin/client/organization_client.rb +12 -11
- data/lib/keycloak-admin/client/realm_client.rb +3 -2
- data/lib/keycloak-admin/client/resource.rb +8 -6
- data/lib/keycloak-admin/client/response.rb +1 -0
- data/lib/keycloak-admin/client/role_client.rb +3 -6
- data/lib/keycloak-admin/client/role_mapper_client.rb +2 -1
- data/lib/keycloak-admin/client/token_client.rb +1 -0
- data/lib/keycloak-admin/client/user_client.rb +70 -47
- data/lib/keycloak-admin/configuration.rb +37 -2
- data/lib/keycloak-admin/error.rb +63 -0
- data/lib/keycloak-admin/path_encoding.rb +24 -0
- data/lib/keycloak-admin/representation/attack_detection_representation.rb +1 -0
- data/lib/keycloak-admin/representation/camel_json.rb +7 -3
- data/lib/keycloak-admin/representation/client_authz_policy_config_representation.rb +1 -0
- data/lib/keycloak-admin/representation/client_authz_policy_representation.rb +1 -0
- data/lib/keycloak-admin/representation/client_authz_resource_representation.rb +1 -0
- data/lib/keycloak-admin/representation/client_authz_scope_representation.rb +1 -0
- data/lib/keycloak-admin/representation/client_representation.rb +4 -5
- data/lib/keycloak-admin/representation/client_scope_representation.rb +1 -0
- data/lib/keycloak-admin/representation/credential_representation.rb +1 -0
- data/lib/keycloak-admin/representation/federated_identity_representation.rb +1 -0
- data/lib/keycloak-admin/representation/group_representation.rb +1 -0
- data/lib/keycloak-admin/representation/identity_provider_mapper_representation.rb +1 -0
- data/lib/keycloak-admin/representation/identity_provider_representation.rb +1 -0
- data/lib/keycloak-admin/representation/impersonation_redirection_representation.rb +1 -0
- data/lib/keycloak-admin/representation/impersonation_representation.rb +1 -0
- data/lib/keycloak-admin/representation/member_representation.rb +1 -0
- data/lib/keycloak-admin/representation/organization_domain_representation.rb +1 -0
- data/lib/keycloak-admin/representation/organization_representation.rb +1 -1
- data/lib/keycloak-admin/representation/protocol_mapper_representation.rb +1 -0
- data/lib/keycloak-admin/representation/realm_representation.rb +1 -0
- data/lib/keycloak-admin/representation/representation.rb +7 -5
- data/lib/keycloak-admin/representation/role_representation.rb +2 -1
- data/lib/keycloak-admin/representation/session_representation.rb +2 -1
- data/lib/keycloak-admin/representation/token_representation.rb +1 -0
- data/lib/keycloak-admin/representation/user_representation.rb +1 -0
- data/lib/keycloak-admin/resource/base_role_containing_resource.rb +4 -1
- data/lib/keycloak-admin/resource/group_resource.rb +1 -0
- data/lib/keycloak-admin/resource/user_resource.rb +1 -0
- data/lib/keycloak-admin/version.rb +2 -1
- data/lib/keycloak-admin.rb +4 -0
- metadata +36 -56
- data/.github/workflows/Dockerfile +0 -24
- data/.github/workflows/ci.yml +0 -94
- data/.github/workflows/release.yml +0 -112
- data/.gitignore +0 -10
- data/.rspec +0 -2
- data/Dockerfile +0 -13
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -54
- data/Rakefile +0 -6
- data/bin/console +0 -9
- data/spec/client/attack_detection_client_spec.rb +0 -102
- data/spec/client/client_authz_permission_client_spec.rb +0 -170
- data/spec/client/client_authz_policy_client_spec.rb +0 -170
- data/spec/client/client_authz_resource_client_spec.rb +0 -150
- data/spec/client/client_authz_scope_client_spec.rb +0 -134
- data/spec/client/client_client_spec.rb +0 -133
- data/spec/client/client_role_mappings_client_spec.rb +0 -83
- data/spec/client/client_scope_client_spec.rb +0 -220
- data/spec/client/client_scope_protocol_mapper_client_spec.rb +0 -230
- data/spec/client/client_spec.rb +0 -101
- data/spec/client/configurable_token_client_spec.rb +0 -34
- data/spec/client/group_client_spec.rb +0 -328
- data/spec/client/identity_provider_client_spec.rb +0 -92
- data/spec/client/organization_client_spec.rb +0 -595
- data/spec/client/realm_client_spec.rb +0 -155
- data/spec/client/resource_spec.rb +0 -223
- data/spec/client/response_spec.rb +0 -68
- data/spec/client/role_client_spec.rb +0 -79
- data/spec/client/role_mapper_client_spec.rb +0 -113
- data/spec/client/token_client_spec.rb +0 -68
- data/spec/client/user_client_spec.rb +0 -418
- data/spec/configuration_spec.rb +0 -150
- data/spec/gemspec_spec.rb +0 -25
- data/spec/integration/client_authorization_spec.rb +0 -93
- data/spec/representation/attack_detection_representation_spec.rb +0 -16
- data/spec/representation/client_authz_permission_representation_spec.rb +0 -52
- data/spec/representation/client_authz_policy_representation_spec.rb +0 -47
- data/spec/representation/client_authz_resource_representation_spec.rb +0 -33
- data/spec/representation/client_authz_scope_representation_spec.rb +0 -19
- data/spec/representation/client_representation_spec.rb +0 -119
- data/spec/representation/client_scope_representation_spec.rb +0 -125
- data/spec/representation/credential_representation_spec.rb +0 -68
- data/spec/representation/group_representation_spec.rb +0 -22
- data/spec/representation/identity_provider_mapper_representation_spec.rb +0 -24
- data/spec/representation/identity_provider_representation_spec.rb +0 -113
- data/spec/representation/impersonation_representation_spec.rb +0 -163
- data/spec/representation/organization_representation_spec.rb +0 -64
- data/spec/representation/protocol_mapper_representation_spec.rb +0 -57
- data/spec/representation/role_representation_spec.rb +0 -37
- data/spec/representation/session_representation_spec.rb +0 -16
- data/spec/representation/user_representation_spec.rb +0 -15
- data/spec/resource/group_resource_spec.rb +0 -14
- data/spec/resource/user_resource_spec.rb +0 -14
- data/spec/spec_helper.rb +0 -36
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
RSpec.describe KeycloakAdmin::RealmClient do
|
|
2
|
-
describe "#realm_url" do
|
|
3
|
-
|
|
4
|
-
let(:realm_name) { nil }
|
|
5
|
-
|
|
6
|
-
before(:each) do
|
|
7
|
-
@built_url = KeycloakAdmin.realm(realm_name).realm_url
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
context "when realm_name is defined" do
|
|
11
|
-
let(:realm_name) { "master2" }
|
|
12
|
-
it "return a proper url with realm_name" do
|
|
13
|
-
expect(@built_url).to eq "http://auth.service.io/auth/realms/master2"
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
context "when realm_name is not defined" do
|
|
18
|
-
let(:realm_name) { nil }
|
|
19
|
-
it "return a proper url without realm_name" do
|
|
20
|
-
expect(@built_url).to eq "http://auth.service.io/auth/realms"
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
describe "#admin_realm_url" do
|
|
26
|
-
|
|
27
|
-
let(:realm_name) { nil }
|
|
28
|
-
|
|
29
|
-
before(:each) do
|
|
30
|
-
@built_url = KeycloakAdmin.realm(realm_name).realm_admin_url
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
context "when realm_name is defined" do
|
|
34
|
-
let(:realm_name) { "master2" }
|
|
35
|
-
it "return a proper url with realm_name" do
|
|
36
|
-
expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/master2"
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
context "when realm_name is not defined" do
|
|
41
|
-
let(:realm_name) { nil }
|
|
42
|
-
it "return a proper url without realm_name" do
|
|
43
|
-
expect(@built_url).to eq "http://auth.service.io/auth/admin/realms"
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
describe "#list" do
|
|
49
|
-
before(:each) do
|
|
50
|
-
@realm_client = KeycloakAdmin.realm('master')
|
|
51
|
-
|
|
52
|
-
stub_token_client
|
|
53
|
-
allow_any_instance_of(KeycloakAdmin::Resource).to receive(:get).and_return '[{"id":"test_realm","realm":"test_realm"}]'
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
it "lists realms" do
|
|
57
|
-
realms = @realm_client.list
|
|
58
|
-
expect(realms.length).to eq 1
|
|
59
|
-
expect(realms[0].realm).to eq "test_realm"
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "passes rest client options" do
|
|
63
|
-
faraday_options = {timeout: 10}
|
|
64
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
65
|
-
|
|
66
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with(
|
|
67
|
-
"http://auth.service.io/auth/admin/realms", faraday_options, anything).and_call_original
|
|
68
|
-
|
|
69
|
-
realms = @realm_client.list
|
|
70
|
-
expect(realms.length).to eq 1
|
|
71
|
-
expect(realms[0].realm).to eq "test_realm"
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
describe "#delete" do
|
|
76
|
-
let(:realm_name) { "valid-realm" }
|
|
77
|
-
|
|
78
|
-
before(:each) do
|
|
79
|
-
@realm_client = KeycloakAdmin.realm(realm_name)
|
|
80
|
-
|
|
81
|
-
stub_token_client
|
|
82
|
-
allow_any_instance_of(KeycloakAdmin::Resource).to receive(:delete)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "delete realm" do
|
|
86
|
-
expect(@realm_client.delete).to be_truthy
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "passes rest client options" do
|
|
90
|
-
faraday_options = {timeout: 10}
|
|
91
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
92
|
-
|
|
93
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with(
|
|
94
|
-
"http://auth.service.io/auth/admin/realms/valid-realm", faraday_options, anything).and_call_original
|
|
95
|
-
|
|
96
|
-
expect(@realm_client.delete).to be_truthy
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
describe "#save" do
|
|
101
|
-
let(:realm_name) { "valid-realm" }
|
|
102
|
-
let(:realm) { KeycloakAdmin::RealmRepresentation.from_hash(
|
|
103
|
-
"id" => realm_name,
|
|
104
|
-
"realm" => realm_name
|
|
105
|
-
)}
|
|
106
|
-
|
|
107
|
-
before(:each) do
|
|
108
|
-
@realm_client = KeycloakAdmin.realm(nil)
|
|
109
|
-
|
|
110
|
-
stub_token_client
|
|
111
|
-
|
|
112
|
-
expect_any_instance_of(KeycloakAdmin::Resource).to receive(:post).with(realm.to_json, anything)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
it "saves a realm" do
|
|
116
|
-
@realm_client.save(realm)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
it "passes rest client options" do
|
|
120
|
-
faraday_options = {timeout: 10}
|
|
121
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
122
|
-
|
|
123
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with(
|
|
124
|
-
"http://auth.service.io/auth/admin/realms", faraday_options, anything).and_call_original
|
|
125
|
-
|
|
126
|
-
@realm_client.save(realm)
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
describe "#update" do
|
|
131
|
-
let(:realm_name) { "valid-realm" }
|
|
132
|
-
let(:realm_json) { { smtpServer: { host: 'test_host' } } }
|
|
133
|
-
|
|
134
|
-
before(:each) do
|
|
135
|
-
@realm_client = KeycloakAdmin.realm(realm_name)
|
|
136
|
-
|
|
137
|
-
stub_token_client
|
|
138
|
-
expect_any_instance_of(KeycloakAdmin::Resource).to receive(:put).with(realm_json.to_json, anything)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
it "updates a realm" do
|
|
142
|
-
@realm_client.update(realm_json)
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
it "passes rest client options" do
|
|
146
|
-
faraday_options = {timeout: 10}
|
|
147
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
148
|
-
|
|
149
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with(
|
|
150
|
-
"http://auth.service.io/auth/admin/realms/valid-realm", faraday_options, anything).and_call_original
|
|
151
|
-
|
|
152
|
-
@realm_client.update(realm_json)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
RSpec.describe KeycloakAdmin::Resource do
|
|
2
|
-
# A real, mutable stand-in for the Faraday::Request builder yielded by
|
|
3
|
-
# connection.get/post/put/delete { |req| ... }.
|
|
4
|
-
FakeRequest = Struct.new(:params, :headers) do
|
|
5
|
-
attr_accessor :body
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
let(:fake_request) { FakeRequest.new({}, {}) }
|
|
9
|
-
let(:fake_response) { double(status: 200, body: "ok", headers: {}, reason_phrase: "OK") }
|
|
10
|
-
|
|
11
|
-
def stub_connection(resource, verb)
|
|
12
|
-
connection = double
|
|
13
|
-
allow(connection).to receive(verb) do |&block|
|
|
14
|
-
block.call(fake_request) if block
|
|
15
|
-
fake_response
|
|
16
|
-
end
|
|
17
|
-
allow(resource).to receive(:connection).and_return(connection)
|
|
18
|
-
connection
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
describe "#connection (the real Faraday connection, not stubbed)" do
|
|
22
|
-
def middleware_classes(resource)
|
|
23
|
-
resource.send(:connection).builder.handlers
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "does not register the logger middleware when no logger is configured" do
|
|
27
|
-
resource = KeycloakAdmin::Resource.new("http://example.com")
|
|
28
|
-
expect(middleware_classes(resource)).to_not include(Faraday::Response::Logger)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "registers the logger middleware when a logger is configured" do
|
|
32
|
-
resource = KeycloakAdmin::Resource.new("http://example.com", {}, Logger.new(IO::NULL))
|
|
33
|
-
expect(middleware_classes(resource)).to include(Faraday::Response::Logger)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it "orders :raise_error before :logger, so a response is logged even when it raises" do
|
|
37
|
-
resource = KeycloakAdmin::Resource.new("http://example.com", {}, Logger.new(IO::NULL))
|
|
38
|
-
handlers = middleware_classes(resource)
|
|
39
|
-
expect(handlers.index(Faraday::Response::RaiseError)).to be < handlers.index(Faraday::Response::Logger)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it "logs method/url/status but never headers, since Faraday logs headers by default and one of them is the bearer token" do
|
|
43
|
-
log_output = StringIO.new
|
|
44
|
-
logger = Logger.new(log_output)
|
|
45
|
-
stubs = Faraday::Adapter::Test::Stubs.new
|
|
46
|
-
stubs.get(//) { [200, {}, "ok"] }
|
|
47
|
-
|
|
48
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/x", {}, logger)
|
|
49
|
-
allow(resource).to receive(:connection) do
|
|
50
|
-
Faraday.new(url: "http://example.com/x") do |f|
|
|
51
|
-
f.response :raise_error
|
|
52
|
-
f.response :logger, logger, headers: false
|
|
53
|
-
f.adapter :test, stubs
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
resource.get(Authorization: "Bearer super-secret-token")
|
|
58
|
-
|
|
59
|
-
expect(log_output.string).to include("request: GET")
|
|
60
|
-
expect(log_output.string).to include("response: Status 200")
|
|
61
|
-
expect(log_output.string).to_not include("super-secret-token")
|
|
62
|
-
expect(log_output.string).to_not include("Authorization")
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
describe "#get" do
|
|
67
|
-
it "humanizes symbol header keys into HTTP header names" do
|
|
68
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
69
|
-
stub_connection(resource, :get)
|
|
70
|
-
|
|
71
|
-
resource.get(Authorization: "Bearer token", content_type: :json, accept: :json)
|
|
72
|
-
|
|
73
|
-
expect(fake_request.headers).to eq(
|
|
74
|
-
"Authorization" => "Bearer token",
|
|
75
|
-
"Content-Type" => "application/json",
|
|
76
|
-
"Accept" => "application/json"
|
|
77
|
-
)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "extracts :params into the query string instead of sending it as a header" do
|
|
81
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
82
|
-
stub_connection(resource, :get)
|
|
83
|
-
|
|
84
|
-
resource.get(Authorization: "Bearer token", params: { search: "jean" })
|
|
85
|
-
|
|
86
|
-
expect(fake_request.params).to eq(search: "jean")
|
|
87
|
-
expect(fake_request.headers).to eq("Authorization" => "Bearer token")
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
it "passes a string content_type through unchanged" do
|
|
91
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
92
|
-
stub_connection(resource, :get)
|
|
93
|
-
|
|
94
|
-
resource.get(content_type: "application/x-www-form-urlencoded")
|
|
95
|
-
|
|
96
|
-
expect(fake_request.headers["Content-Type"]).to eq "application/x-www-form-urlencoded"
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "does not set a body" do
|
|
100
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
101
|
-
stub_connection(resource, :get)
|
|
102
|
-
|
|
103
|
-
resource.get({})
|
|
104
|
-
|
|
105
|
-
expect(fake_request.body).to be_nil
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "wraps the Faraday response in a KeycloakAdmin::Response" do
|
|
109
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
110
|
-
stub_connection(resource, :get)
|
|
111
|
-
|
|
112
|
-
expect(resource.get({})).to be_a KeycloakAdmin::Response
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
describe "#post" do
|
|
117
|
-
it "sends a pre-serialized string payload as the body unchanged" do
|
|
118
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
119
|
-
stub_connection(resource, :post)
|
|
120
|
-
|
|
121
|
-
resource.post('{"username":"jean"}', content_type: :json)
|
|
122
|
-
|
|
123
|
-
expect(fake_request.body).to eq '{"username":"jean"}'
|
|
124
|
-
expect(fake_request.headers["Content-Type"]).to eq "application/json"
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
it "form-encodes a Hash payload" do
|
|
128
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
129
|
-
stub_connection(resource, :post)
|
|
130
|
-
|
|
131
|
-
resource.post({ email: "a@b.com", firstName: "Jean Yves" }, {})
|
|
132
|
-
|
|
133
|
-
expect(fake_request.body).to eq "email=a%40b.com&firstName=Jean+Yves"
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
it "stamps Content-Type: application/x-www-form-urlencoded for a Hash payload when none was set" do
|
|
137
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
138
|
-
stub_connection(resource, :post)
|
|
139
|
-
|
|
140
|
-
resource.post({ id: "42" }, {})
|
|
141
|
-
|
|
142
|
-
expect(fake_request.headers["Content-Type"]).to eq "application/x-www-form-urlencoded"
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
it "does not override an explicit Content-Type for a Hash payload" do
|
|
146
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users")
|
|
147
|
-
stub_connection(resource, :post)
|
|
148
|
-
|
|
149
|
-
resource.post({ id: "42" }, content_type: "application/vnd.custom+form")
|
|
150
|
-
|
|
151
|
-
expect(fake_request.headers["Content-Type"]).to eq "application/vnd.custom+form"
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
describe "#delete" do
|
|
156
|
-
it "sends no body and only the given headers" do
|
|
157
|
-
resource = KeycloakAdmin::Resource.new("http://example.com/users/1")
|
|
158
|
-
stub_connection(resource, :delete)
|
|
159
|
-
|
|
160
|
-
resource.delete(Authorization: "Bearer token")
|
|
161
|
-
|
|
162
|
-
expect(fake_request.body).to be_nil
|
|
163
|
-
expect(fake_request.headers).to eq("Authorization" => "Bearer token")
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
describe ".execute (RestClient::Request.execute equivalent)" do
|
|
168
|
-
it "dispatches an arbitrary method with a payload, including DELETE with a body" do
|
|
169
|
-
resource_instance = KeycloakAdmin::Resource.new("http://example.com/mappings")
|
|
170
|
-
allow(KeycloakAdmin::Resource).to receive(:new).and_return(resource_instance)
|
|
171
|
-
stub_connection(resource_instance, :delete)
|
|
172
|
-
|
|
173
|
-
KeycloakAdmin::Resource.execute(
|
|
174
|
-
method: :delete,
|
|
175
|
-
url: "http://example.com/mappings",
|
|
176
|
-
payload: '[{"id":"1"}]',
|
|
177
|
-
headers: { content_type: :json }
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
expect(fake_request.body).to eq '[{"id":"1"}]'
|
|
181
|
-
expect(fake_request.headers["Content-Type"]).to eq "application/json"
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
it "forwards non-method/url/payload/headers keys as connection options" do
|
|
185
|
-
resource_instance = KeycloakAdmin::Resource.new("http://example.com/x")
|
|
186
|
-
expected_options = { timeout: 5 }
|
|
187
|
-
stub_connection(resource_instance, :get)
|
|
188
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with("http://example.com/x", expected_options, nil).and_return(resource_instance)
|
|
189
|
-
|
|
190
|
-
KeycloakAdmin::Resource.execute(method: :get, url: "http://example.com/x", headers: {}, timeout: 5)
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
it "extracts :logger and passes it positionally instead of leaving it in connection options" do
|
|
194
|
-
resource_instance = KeycloakAdmin::Resource.new("http://example.com/x")
|
|
195
|
-
logger = Logger.new(IO::NULL)
|
|
196
|
-
stub_connection(resource_instance, :get)
|
|
197
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with("http://example.com/x", {}, logger).and_return(resource_instance)
|
|
198
|
-
|
|
199
|
-
KeycloakAdmin::Resource.execute(method: :get, url: "http://example.com/x", headers: {}, logger: logger)
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
describe ".put (RestClient.put shorthand)" do
|
|
204
|
-
it "posts without requiring any connection options" do
|
|
205
|
-
resource_instance = KeycloakAdmin::Resource.new("http://example.com/x")
|
|
206
|
-
allow(KeycloakAdmin::Resource).to receive(:new).and_return(resource_instance)
|
|
207
|
-
stub_connection(resource_instance, :put)
|
|
208
|
-
|
|
209
|
-
KeycloakAdmin::Resource.put("http://example.com/x", "body", {})
|
|
210
|
-
|
|
211
|
-
expect(fake_request.body).to eq "body"
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
it "forwards the given logger to the underlying Resource" do
|
|
215
|
-
resource_instance = KeycloakAdmin::Resource.new("http://example.com/x")
|
|
216
|
-
logger = Logger.new(IO::NULL)
|
|
217
|
-
stub_connection(resource_instance, :put)
|
|
218
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with("http://example.com/x", {}, logger).and_return(resource_instance)
|
|
219
|
-
|
|
220
|
-
KeycloakAdmin::Resource.put("http://example.com/x", "body", {}, logger)
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
end
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
RSpec.describe KeycloakAdmin::Response do
|
|
2
|
-
def fake_faraday_response(status: 200, body: "", headers: {}, reason_phrase: "OK")
|
|
3
|
-
double(status: status, body: body, headers: headers, reason_phrase: reason_phrase)
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
describe "body-as-string behavior (RestClient::Response was a String subclass)" do
|
|
7
|
-
it "behaves like the raw body string" do
|
|
8
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(body: '{"a":1}'))
|
|
9
|
-
expect(response).to eq '{"a":1}'
|
|
10
|
-
expect(JSON.parse(response)).to eq({ "a" => 1 })
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
it "supports String methods relied on by callers, e.g. #to_i" do
|
|
14
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(body: "42"))
|
|
15
|
-
expect(response.to_i).to eq 42
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it "exposes #body returning the same content" do
|
|
19
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(body: "hello"))
|
|
20
|
-
expect(response.body).to eq "hello"
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
describe "#status / #code / #reason_phrase" do
|
|
25
|
-
it "exposes the HTTP status" do
|
|
26
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(status: 201))
|
|
27
|
-
expect(response.status).to eq 201
|
|
28
|
-
expect(response.code).to eq 201
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "exposes the reason phrase" do
|
|
32
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(reason_phrase: "Created"))
|
|
33
|
-
expect(response.reason_phrase).to eq "Created"
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
describe "#headers" do
|
|
38
|
-
it "symbolizes header names the way RestClient did (downcased, dash to underscore)" do
|
|
39
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(headers: { "Location" => "/users/42", "Content-Type" => "application/json" }))
|
|
40
|
-
expect(response.headers[:location]).to eq "/users/42"
|
|
41
|
-
expect(response.headers[:content_type]).to eq "application/json"
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it "splits a single Set-Cookie header into a one-element array" do
|
|
45
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(headers: { "Set-Cookie" => "a=1; Path=/" }))
|
|
46
|
-
expect(response.headers[:set_cookie]).to eq ["a=1; Path=/"]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it "splits multiple Set-Cookie headers joined by Faraday's net_http adapter" do
|
|
50
|
-
joined = "KEYCLOAK_SESSION=abc; Path=/, KEYCLOAK_IDENTITY=def; Path=/, AUTH_SESSION_ID=ghi; Path=/"
|
|
51
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(headers: { "Set-Cookie" => joined }))
|
|
52
|
-
expect(response.headers[:set_cookie]).to eq [
|
|
53
|
-
"KEYCLOAK_SESSION=abc; Path=/",
|
|
54
|
-
"KEYCLOAK_IDENTITY=def; Path=/",
|
|
55
|
-
"AUTH_SESSION_ID=ghi; Path=/"
|
|
56
|
-
]
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it "does not split on a comma embedded in a cookie's own Expires attribute" do
|
|
60
|
-
joined = "a=1; Expires=Wed, 09 Jun 2027 10:18:14 GMT; Path=/, b=2; Path=/"
|
|
61
|
-
response = KeycloakAdmin::Response.new(fake_faraday_response(headers: { "Set-Cookie" => joined }))
|
|
62
|
-
expect(response.headers[:set_cookie]).to eq [
|
|
63
|
-
"a=1; Expires=Wed, 09 Jun 2027 10:18:14 GMT; Path=/",
|
|
64
|
-
"b=2; Path=/"
|
|
65
|
-
]
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
RSpec.describe KeycloakAdmin::RoleClient do
|
|
2
|
-
describe "#roles_url" do
|
|
3
|
-
let(:realm_name) { "valid-realm" }
|
|
4
|
-
|
|
5
|
-
it "return a proper url without role id" do
|
|
6
|
-
@built_url = KeycloakAdmin.realm(realm_name).roles.roles_url
|
|
7
|
-
expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/valid-realm/roles"
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
describe "#role_id_url" do
|
|
12
|
-
let(:realm_name) { "valid-realm" }
|
|
13
|
-
let(:role_id) { "95985b21-d884-4bbd-b852-cb8cd365afc2" }
|
|
14
|
-
|
|
15
|
-
it "return a proper url with the role id" do
|
|
16
|
-
@built_url = KeycloakAdmin.realm(realm_name).roles.role_id_url(role_id)
|
|
17
|
-
expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/valid-realm/roles-by-id/95985b21-d884-4bbd-b852-cb8cd365afc2"
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
describe "#list" do
|
|
22
|
-
let(:realm_name) { "valid-realm" }
|
|
23
|
-
|
|
24
|
-
before(:each) do
|
|
25
|
-
@role_client = KeycloakAdmin.realm(realm_name).roles
|
|
26
|
-
|
|
27
|
-
stub_token_client
|
|
28
|
-
allow_any_instance_of(KeycloakAdmin::Resource).to receive(:get).and_return '[{"id":"test_role_id","name":"test_role_name"}]'
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "lists roles" do
|
|
32
|
-
roles = @role_client.list
|
|
33
|
-
expect(roles.length).to eq 1
|
|
34
|
-
expect(roles[0].name).to eq "test_role_name"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it "passes rest client options" do
|
|
38
|
-
faraday_options = {timeout: 10}
|
|
39
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
40
|
-
|
|
41
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with(
|
|
42
|
-
"http://auth.service.io/auth/admin/realms/valid-realm/roles", faraday_options, anything).and_call_original
|
|
43
|
-
|
|
44
|
-
roles = @role_client.list
|
|
45
|
-
expect(roles.length).to eq 1
|
|
46
|
-
expect(roles[0].name).to eq "test_role_name"
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
describe "#save" do
|
|
51
|
-
let(:realm_name) { "valid-realm" }
|
|
52
|
-
let(:role) { KeycloakAdmin::RoleRepresentation.from_hash(
|
|
53
|
-
"name" => "test_role_name",
|
|
54
|
-
"composite" => false,
|
|
55
|
-
"clientRole" => false
|
|
56
|
-
)}
|
|
57
|
-
|
|
58
|
-
before(:each) do
|
|
59
|
-
@role_client = KeycloakAdmin.realm(realm_name).roles
|
|
60
|
-
|
|
61
|
-
stub_token_client
|
|
62
|
-
expect_any_instance_of(KeycloakAdmin::Resource).to receive(:post).with(role.to_json, anything)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
it "saves a role" do
|
|
66
|
-
@role_client.save(role)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "passes rest client options" do
|
|
70
|
-
faraday_options = {timeout: 10}
|
|
71
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
72
|
-
|
|
73
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with(
|
|
74
|
-
"http://auth.service.io/auth/admin/realms/valid-realm/roles", faraday_options, anything).and_call_original
|
|
75
|
-
|
|
76
|
-
@role_client.save(role)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
RSpec.describe KeycloakAdmin::RoleMapperClient do
|
|
2
|
-
describe "#available_url" do
|
|
3
|
-
let(:realm_name) { "valid-realm" }
|
|
4
|
-
let(:user_id) { "test_user" }
|
|
5
|
-
|
|
6
|
-
before(:each) do
|
|
7
|
-
@built_url = KeycloakAdmin.realm(realm_name).user(user_id).role_mapper.realm_level_url
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
it "return a proper url" do
|
|
11
|
-
expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/valid-realm/users/test_user/role-mappings/realm"
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
describe "#list" do
|
|
16
|
-
let(:realm_name) { "valid-realm" }
|
|
17
|
-
let(:user_id) { "test_user" }
|
|
18
|
-
|
|
19
|
-
before(:each) do
|
|
20
|
-
@role_mapper_client = KeycloakAdmin.realm(realm_name).user(user_id).role_mapper
|
|
21
|
-
|
|
22
|
-
stub_token_client
|
|
23
|
-
allow_any_instance_of(KeycloakAdmin::Resource).to receive(:get)
|
|
24
|
-
.and_return '[{"id":"test_role_id","name":"test_role_name","composite": false}]'
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it "list user realm-level role mappings" do
|
|
28
|
-
roles = @role_mapper_client.list
|
|
29
|
-
expect(roles.length).to eq 1
|
|
30
|
-
expect(roles[0].id).to eq "test_role_id"
|
|
31
|
-
expect(roles[0].name).to eq "test_role_name"
|
|
32
|
-
expect(roles[0].composite).to be false
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
describe "#save_realm_level" do
|
|
37
|
-
let(:realm_name) { "valid-realm" }
|
|
38
|
-
let(:user_id) { "test_user" }
|
|
39
|
-
let(:role_list) { [
|
|
40
|
-
KeycloakAdmin::RoleRepresentation.from_hash(
|
|
41
|
-
"name" => "test_role_name",
|
|
42
|
-
"composite" => false,
|
|
43
|
-
"clientRole" => false
|
|
44
|
-
)
|
|
45
|
-
] }
|
|
46
|
-
|
|
47
|
-
before(:each) do
|
|
48
|
-
@role_mapper_client = KeycloakAdmin.realm(realm_name).user(user_id).role_mapper
|
|
49
|
-
|
|
50
|
-
stub_token_client
|
|
51
|
-
expect_any_instance_of(KeycloakAdmin::Resource).to receive(:post).with(role_list.to_json, anything)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "saves realm-elevel role mappings" do
|
|
55
|
-
@role_mapper_client.save_realm_level(role_list)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it "passes rest client options" do
|
|
59
|
-
faraday_options = {timeout: 10}
|
|
60
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
61
|
-
|
|
62
|
-
expect(KeycloakAdmin::Resource).to receive(:new).with(
|
|
63
|
-
"http://auth.service.io/auth/admin/realms/valid-realm/users/test_user/role-mappings/realm", faraday_options, anything).and_call_original
|
|
64
|
-
|
|
65
|
-
@role_mapper_client.save_realm_level(role_list)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
describe "#remove_realm_level" do
|
|
70
|
-
let(:realm_name) { "valid-realm" }
|
|
71
|
-
let(:user_id) { "test_user" }
|
|
72
|
-
let(:role_list) { [
|
|
73
|
-
KeycloakAdmin::RoleRepresentation.from_hash(
|
|
74
|
-
"id" => "d9e3376b-f602-4086-8eee-89fea73c73ea"
|
|
75
|
-
)
|
|
76
|
-
] }
|
|
77
|
-
let(:expected_url) { "http://auth.service.io/auth/admin/realms/valid-realm/users/test_user/role-mappings/realm" }
|
|
78
|
-
|
|
79
|
-
before(:each) do
|
|
80
|
-
@role_mapper_client = KeycloakAdmin.realm(realm_name).user(user_id).role_mapper
|
|
81
|
-
|
|
82
|
-
stub_token_client
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "removes realm-level role mappings" do
|
|
86
|
-
expect(KeycloakAdmin::Resource).to receive(:execute).with(
|
|
87
|
-
hash_including(
|
|
88
|
-
method: :delete,
|
|
89
|
-
url: expected_url,
|
|
90
|
-
payload: role_list.to_json
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
@role_mapper_client.remove_realm_level(role_list)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it "passes rest client options" do
|
|
98
|
-
faraday_options = {timeout: 10}
|
|
99
|
-
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:faraday_options).and_return faraday_options
|
|
100
|
-
|
|
101
|
-
expect(KeycloakAdmin::Resource).to receive(:execute).with(
|
|
102
|
-
hash_including(
|
|
103
|
-
method: :delete,
|
|
104
|
-
url: expected_url,
|
|
105
|
-
payload: role_list.to_json,
|
|
106
|
-
timeout: 10
|
|
107
|
-
)
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
@role_mapper_client.remove_realm_level(role_list)
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|