keycloak-admin 2.0.2 → 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 +27 -0
- data/MIT-LICENSE +18 -17
- data/README.md +66 -5
- data/keycloak-admin.gemspec +1 -0
- data/lib/keycloak-admin/client/attack_detection_client.rb +2 -1
- data/lib/keycloak-admin/client/client.rb +17 -4
- data/lib/keycloak-admin/client/client_authz_permission_client.rb +4 -3
- data/lib/keycloak-admin/client/client_authz_policy_client.rb +3 -2
- data/lib/keycloak-admin/client/client_authz_resource_client.rb +14 -10
- data/lib/keycloak-admin/client/client_authz_scope_client.rb +4 -3
- 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 +13 -4
- data/lib/keycloak-admin/client/identity_provider_client.rb +2 -1
- data/lib/keycloak-admin/client/organization_client.rb +6 -5
- 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 +63 -44
- data/lib/keycloak-admin/configuration.rb +37 -2
- data/lib/keycloak-admin/error.rb +1 -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 +3 -0
- metadata +16 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require "faraday"
|
|
2
3
|
require "uri"
|
|
3
4
|
|
|
@@ -18,13 +19,11 @@ module KeycloakAdmin
|
|
|
18
19
|
new(url, options, logger).send(:request, method, payload, headers)
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def self.put(url, payload, headers = {}, logger = nil)
|
|
22
|
-
new(url, {}, logger).put(payload, headers)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
22
|
def initialize(url, options = {}, logger = nil)
|
|
23
|
+
options = (options || {}).dup
|
|
24
|
+
@adapter = options.delete(:adapter)
|
|
26
25
|
@url = url
|
|
27
|
-
@options = options
|
|
26
|
+
@options = options
|
|
28
27
|
@logger = logger
|
|
29
28
|
end
|
|
30
29
|
|
|
@@ -75,7 +74,10 @@ module KeycloakAdmin
|
|
|
75
74
|
# headers by default, which would print the bearer token on every call; headers: false
|
|
76
75
|
# keeps this to method/url/status only. Bodies are already off by Faraday's own default.
|
|
77
76
|
f.response :logger, @logger, headers: false if @logger
|
|
78
|
-
|
|
77
|
+
# Faraday's default net_http adapter wraps every request in http.start, which reopens
|
|
78
|
+
# the connection each time; config.faraday_adapter lets a caller swap in a pooling one.
|
|
79
|
+
# Splatted so an adapter needing arguments can be given as [:name, options].
|
|
80
|
+
f.adapter(*Array(@adapter || Faraday.default_adapter))
|
|
79
81
|
end
|
|
80
82
|
end
|
|
81
83
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
class RoleClient < Client
|
|
3
4
|
def initialize(configuration, realm_client)
|
|
@@ -15,8 +16,6 @@ module KeycloakAdmin
|
|
|
15
16
|
|
|
16
17
|
# Returns the role representation for the specified role name
|
|
17
18
|
def get(name)
|
|
18
|
-
# allows special characters in the name like space
|
|
19
|
-
name = URI.encode_uri_component(name)
|
|
20
19
|
response = execute_http do
|
|
21
20
|
resource(role_name_url(name)).get(headers)
|
|
22
21
|
end
|
|
@@ -25,8 +24,6 @@ module KeycloakAdmin
|
|
|
25
24
|
|
|
26
25
|
# Lists all groups that have the specified role name assigned
|
|
27
26
|
def list_groups(name)
|
|
28
|
-
# allows special characters in the name like space
|
|
29
|
-
name = URI.encode_uri_component(name)
|
|
30
27
|
response = execute_http do
|
|
31
28
|
resource("#{role_name_url(name)}/groups").get(headers)
|
|
32
29
|
end
|
|
@@ -49,11 +46,11 @@ module KeycloakAdmin
|
|
|
49
46
|
end
|
|
50
47
|
|
|
51
48
|
def role_id_url(id)
|
|
52
|
-
"#{@realm_client.realm_admin_url}/roles-by-id/#{id}"
|
|
49
|
+
"#{@realm_client.realm_admin_url}/roles-by-id/#{encode_segment(id)}"
|
|
53
50
|
end
|
|
54
51
|
|
|
55
52
|
def role_name_url(name)
|
|
56
|
-
"#{@realm_client.realm_admin_url}/roles/#{name}"
|
|
53
|
+
"#{@realm_client.realm_admin_url}/roles/#{encode_segment(name)}"
|
|
57
54
|
end
|
|
58
55
|
end
|
|
59
56
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
class RoleMapperClient < Client
|
|
3
4
|
def initialize(configuration, user_resource)
|
|
@@ -23,7 +24,7 @@ module KeycloakAdmin
|
|
|
23
24
|
def remove_realm_level(role_representation_list)
|
|
24
25
|
execute_http do
|
|
25
26
|
Resource.execute(
|
|
26
|
-
|
|
27
|
+
connection_options.merge(
|
|
27
28
|
method: :delete,
|
|
28
29
|
url: realm_level_url,
|
|
29
30
|
payload: create_payload(role_representation_list),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
class UserClient < Client
|
|
3
4
|
def initialize(configuration, realm_client)
|
|
@@ -6,55 +7,61 @@ module KeycloakAdmin
|
|
|
6
7
|
@realm_client = realm_client
|
|
7
8
|
end
|
|
8
9
|
|
|
10
|
+
# Reads the id of the new user off the Location header rather than searching for it
|
|
11
|
+
# afterwards: Keycloak's `search` parameter matches a substring of the username, email,
|
|
12
|
+
# first name or last name, so an existing user merely containing this email was returned
|
|
13
|
+
# instead of the one just created.
|
|
9
14
|
def create!(username, email, password, email_verified, locale, attributes={})
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
response = post_user(build(username, email, password, email_verified, locale, attributes))
|
|
16
|
+
get(created_id(response))
|
|
12
17
|
end
|
|
13
18
|
|
|
14
19
|
def save(user_representation)
|
|
15
|
-
|
|
16
|
-
resource(users_url).post(
|
|
17
|
-
create_payload(user_representation), headers
|
|
18
|
-
)
|
|
19
|
-
end
|
|
20
|
+
post_user(user_representation)
|
|
20
21
|
user_representation
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
# pay attention that, since Keycloak 24.0.4, partial updates of attributes are not authorized anymore
|
|
24
25
|
def update(user_id, user_representation_body)
|
|
25
26
|
raise ArgumentError.new("user_id must be defined") if user_id.nil?
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
execute_http do
|
|
28
|
+
Resource.execute(
|
|
29
|
+
connection_options.merge(
|
|
30
|
+
method: :put,
|
|
31
|
+
url: users_url(user_id),
|
|
32
|
+
payload: create_payload(user_representation_body),
|
|
33
|
+
headers: headers,
|
|
34
|
+
logger: @configuration.logger
|
|
35
|
+
)
|
|
33
36
|
)
|
|
34
|
-
|
|
37
|
+
end
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
def add_group(user_id, group_id)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
execute_http do
|
|
42
|
+
Resource.execute(
|
|
43
|
+
connection_options.merge(
|
|
44
|
+
method: :put,
|
|
45
|
+
url: "#{users_url(user_id)}/groups/#{encode_segment(group_id)}",
|
|
46
|
+
payload: create_payload({}),
|
|
47
|
+
headers: headers,
|
|
48
|
+
logger: @configuration.logger
|
|
49
|
+
)
|
|
45
50
|
)
|
|
46
|
-
|
|
51
|
+
end
|
|
47
52
|
end
|
|
48
53
|
|
|
49
54
|
def remove_group(user_id, group_id)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
execute_http do
|
|
56
|
+
Resource.execute(
|
|
57
|
+
connection_options.merge(
|
|
58
|
+
method: :delete,
|
|
59
|
+
url: "#{users_url(user_id)}/groups/#{encode_segment(group_id)}",
|
|
60
|
+
headers: headers,
|
|
61
|
+
logger: @configuration.logger
|
|
62
|
+
)
|
|
56
63
|
)
|
|
57
|
-
|
|
64
|
+
end
|
|
58
65
|
end
|
|
59
66
|
|
|
60
67
|
def add_client_roles_on_user(user_id, client_id, role_representations)
|
|
@@ -94,8 +101,12 @@ module KeycloakAdmin
|
|
|
94
101
|
JSON.parse(response).map { |user_as_hash| UserRepresentation.from_hash(user_as_hash) }
|
|
95
102
|
end
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
# Keycloak answers this endpoint with at most 100 users unless `max` says otherwise, so a
|
|
105
|
+
# bare `list` silently truncates a larger realm. Passing neither bound sends no query
|
|
106
|
+
# parameter at all, exactly as before.
|
|
107
|
+
def list(first: nil, max: nil)
|
|
108
|
+
pagination = {first: first, max: max}.compact
|
|
109
|
+
search(pagination.empty? ? nil : pagination)
|
|
99
110
|
end
|
|
100
111
|
|
|
101
112
|
def delete(user_id)
|
|
@@ -112,13 +123,13 @@ module KeycloakAdmin
|
|
|
112
123
|
JSON.parse(response).map { |group_as_hash| GroupRepresentation.from_hash(group_as_hash) }
|
|
113
124
|
end
|
|
114
125
|
|
|
115
|
-
def update_password(user_id, new_password)
|
|
126
|
+
def update_password(user_id, new_password, temporary: false)
|
|
116
127
|
execute_http do
|
|
117
128
|
Resource.execute(
|
|
118
|
-
|
|
129
|
+
connection_options.merge(
|
|
119
130
|
method: :put,
|
|
120
131
|
url: reset_password_url(user_id),
|
|
121
|
-
payload: { type: "password", value: new_password, temporary:
|
|
132
|
+
payload: { type: "password", value: new_password, temporary: temporary }.to_json,
|
|
122
133
|
headers: headers,
|
|
123
134
|
logger: @configuration.logger
|
|
124
135
|
)
|
|
@@ -148,16 +159,16 @@ module KeycloakAdmin
|
|
|
148
159
|
|
|
149
160
|
url = execute_actions_email_url(user_id)
|
|
150
161
|
url = "#{url}?#{build_query(query)}" unless query.empty?
|
|
151
|
-
|
|
162
|
+
resource(url).put(create_payload(actions), headers)
|
|
152
163
|
end
|
|
153
164
|
user_id
|
|
154
165
|
end
|
|
155
166
|
|
|
156
167
|
def impersonate(user_id)
|
|
157
|
-
impersonation = get_redirect_impersonation(user_id)
|
|
158
168
|
response = execute_http do
|
|
169
|
+
impersonation = get_redirect_impersonation(user_id)
|
|
159
170
|
Resource.execute(
|
|
160
|
-
|
|
171
|
+
connection_options.merge(
|
|
161
172
|
method: :post,
|
|
162
173
|
url: impersonation.impersonation_url,
|
|
163
174
|
payload: impersonation.body.to_json,
|
|
@@ -183,7 +194,7 @@ module KeycloakAdmin
|
|
|
183
194
|
|
|
184
195
|
execute_http do
|
|
185
196
|
Resource.execute(
|
|
186
|
-
|
|
197
|
+
connection_options.merge(
|
|
187
198
|
method: :post,
|
|
188
199
|
url: logout_url(user_id),
|
|
189
200
|
headers: headers,
|
|
@@ -206,7 +217,7 @@ module KeycloakAdmin
|
|
|
206
217
|
|
|
207
218
|
execute_http do
|
|
208
219
|
Resource.execute(
|
|
209
|
-
|
|
220
|
+
connection_options.merge(
|
|
210
221
|
method: :post,
|
|
211
222
|
url: federated_identity_url(user_id, idp_id),
|
|
212
223
|
payload: fed_id_rep.to_json,
|
|
@@ -225,14 +236,14 @@ module KeycloakAdmin
|
|
|
225
236
|
|
|
226
237
|
def users_url(id=nil)
|
|
227
238
|
if id
|
|
228
|
-
"#{@realm_client.realm_admin_url}/users/#{id}"
|
|
239
|
+
"#{@realm_client.realm_admin_url}/users/#{encode_segment(id)}"
|
|
229
240
|
else
|
|
230
241
|
"#{@realm_client.realm_admin_url}/users"
|
|
231
242
|
end
|
|
232
243
|
end
|
|
233
244
|
|
|
234
245
|
def user_client_role_mappings_url(user_id, client_id)
|
|
235
|
-
"#{users_url(user_id)}/role-mappings/clients/#{client_id}"
|
|
246
|
+
"#{users_url(user_id)}/role-mappings/clients/#{encode_segment(client_id)}"
|
|
236
247
|
end
|
|
237
248
|
|
|
238
249
|
def reset_password_url(user_id)
|
|
@@ -263,7 +274,7 @@ module KeycloakAdmin
|
|
|
263
274
|
def federated_identity_url(user_id, identity_provider)
|
|
264
275
|
raise ArgumentError.new("user_id must be defined") if user_id.nil?
|
|
265
276
|
raise ArgumentError.new("identity_provider must be defined") if identity_provider.nil?
|
|
266
|
-
"#{users_url(user_id)}/federated-identity/#{identity_provider}"
|
|
277
|
+
"#{users_url(user_id)}/federated-identity/#{encode_segment(identity_provider)}"
|
|
267
278
|
end
|
|
268
279
|
|
|
269
280
|
def logout_url(user_id)
|
|
@@ -274,13 +285,21 @@ module KeycloakAdmin
|
|
|
274
285
|
|
|
275
286
|
private
|
|
276
287
|
|
|
288
|
+
def post_user(user_representation)
|
|
289
|
+
execute_http do
|
|
290
|
+
resource(users_url).post(
|
|
291
|
+
create_payload(user_representation), headers
|
|
292
|
+
)
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
277
296
|
def build(username, email, password, email_verified, locale, attributes={})
|
|
278
297
|
user = UserRepresentation.new
|
|
279
298
|
user.email = email
|
|
280
299
|
user.username = username
|
|
281
300
|
user.email_verified = email_verified
|
|
282
301
|
user.enabled = true
|
|
283
|
-
user.attributes = attributes || {}
|
|
302
|
+
user.attributes = (attributes || {}).dup
|
|
284
303
|
user.attributes[:locale] = locale if locale
|
|
285
304
|
user.add_credential(CredentialRepresentation.from_password(password)) if !password.nil?
|
|
286
305
|
user
|
|
@@ -1,13 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require "base64"
|
|
2
3
|
|
|
3
4
|
module KeycloakAdmin
|
|
4
5
|
class Configuration
|
|
5
|
-
attr_accessor :server_url, :server_domain, :client_id, :client_secret, :client_realm_name, :use_service_account, :username, :password, :logger, :faraday_options
|
|
6
|
+
attr_accessor :server_url, :server_domain, :client_id, :client_secret, :client_realm_name, :use_service_account, :username, :password, :logger, :faraday_options, :faraday_adapter
|
|
6
7
|
|
|
7
8
|
# Treat a cached token as expired this many seconds before its real expiry, so it
|
|
8
9
|
# cannot go stale between the check below and the request that relies on it.
|
|
9
10
|
TOKEN_EXPIRY_SAFETY_MARGIN_SECONDS = 10
|
|
10
11
|
|
|
12
|
+
FILTERED_ATTRIBUTES = %i[@client_secret @password @cached_token].freeze
|
|
13
|
+
FILTERED_PLACEHOLDER = "[FILTERED]".freeze
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@token_mutex = Mutex.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def inspect
|
|
20
|
+
rendered = instance_variables.map do |name|
|
|
21
|
+
value = instance_variable_get(name)
|
|
22
|
+
shown = if FILTERED_ATTRIBUTES.include?(name) && !value.nil?
|
|
23
|
+
FILTERED_PLACEHOLDER
|
|
24
|
+
else
|
|
25
|
+
value.inspect
|
|
26
|
+
end
|
|
27
|
+
"#{name}=#{shown}"
|
|
28
|
+
end
|
|
29
|
+
"#<#{self.class.name} #{rendered.join(", ")}>"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Returns the cached token, fetching one through the block if there is none.
|
|
33
|
+
# The block runs at most once across threads.
|
|
34
|
+
def fetch_token_once
|
|
35
|
+
token = cached_token
|
|
36
|
+
if token.nil?
|
|
37
|
+
@token_mutex.synchronize do
|
|
38
|
+
token = cached_token
|
|
39
|
+
token.nil? ? cache_token(yield) : token
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
token
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
11
46
|
# Returns the cached TokenRepresentation, or nil if there is none or it is (about to be) expired.
|
|
12
47
|
def cached_token
|
|
13
48
|
return nil if @token_expires_at.nil? || Time.now >= @token_expires_at
|
|
@@ -22,8 +57,8 @@ module KeycloakAdmin
|
|
|
22
57
|
end
|
|
23
58
|
|
|
24
59
|
def clear_cached_token!
|
|
25
|
-
@cached_token = nil
|
|
26
60
|
@token_expires_at = nil
|
|
61
|
+
@cached_token = nil
|
|
27
62
|
end
|
|
28
63
|
|
|
29
64
|
def body_for_token_retrieval
|
data/lib/keycloak-admin/error.rb
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "uri"
|
|
3
|
+
|
|
4
|
+
module KeycloakAdmin
|
|
5
|
+
# Percent-encoding for the identifiers interpolated into a URL path.
|
|
6
|
+
#
|
|
7
|
+
# Included by Client and BaseRoleContainingResource, which have no common ancestor but
|
|
8
|
+
# both build URLs out of caller-supplied values.
|
|
9
|
+
module PathEncoding
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
# Encodes '/' as %2F too, so an identifier can never open a path segment of its own.
|
|
13
|
+
# Values that are already URL-safe - the UUIDs Keycloak hands out - come out unchanged,
|
|
14
|
+
# so this is a no-op for the usual case.
|
|
15
|
+
#
|
|
16
|
+
# Without it, any identifier holding a character that is illegal in a URI (a space, most
|
|
17
|
+
# obviously) made Ruby's URI parser raise URI::InvalidURIError before the request was
|
|
18
|
+
# ever sent. That is reachable with values users choose themselves, identity provider
|
|
19
|
+
# aliases being the clearest case.
|
|
20
|
+
def encode_segment(value)
|
|
21
|
+
URI.encode_uri_component(value.to_s)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
module CamelJson
|
|
3
4
|
|
|
4
5
|
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
word = lower_case_and_underscored_word.to_s
|
|
7
|
+
if word.empty?
|
|
8
|
+
word
|
|
9
|
+
elsif first_letter_in_uppercase
|
|
10
|
+
word.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
|
7
11
|
else
|
|
8
|
-
|
|
12
|
+
word[0] + camelize(word)[1..-1]
|
|
9
13
|
end
|
|
10
14
|
end
|
|
11
15
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
class ClientRepresentation < Representation
|
|
3
4
|
attr_accessor :id,
|
|
@@ -26,7 +27,6 @@ module KeycloakAdmin
|
|
|
26
27
|
:authentication_flow_binding_overrides,
|
|
27
28
|
:full_scope_allowed,
|
|
28
29
|
:node_re_registration_timeout,
|
|
29
|
-
:attributes,
|
|
30
30
|
:protocol_mappers,
|
|
31
31
|
:default_client_scopes,
|
|
32
32
|
:optional_client_scopes,
|
|
@@ -41,9 +41,9 @@ module KeycloakAdmin
|
|
|
41
41
|
client.client_authenticator_type = hash["clientAuthenticatorType"]
|
|
42
42
|
client.always_display_in_console = hash["alwaysDisplayInConsole"] || false
|
|
43
43
|
client.surrogate_auth_required = hash["surrogateAuthRequired"] || false
|
|
44
|
-
client.redirect_uris = hash["redirectUris"] ||
|
|
45
|
-
client.web_origins = hash["webOrigins"] ||
|
|
46
|
-
client.not_before = hash["notBefore"] ||
|
|
44
|
+
client.redirect_uris = hash["redirectUris"] || []
|
|
45
|
+
client.web_origins = hash["webOrigins"] || []
|
|
46
|
+
client.not_before = hash["notBefore"] || 0
|
|
47
47
|
client.bearer_only = hash["bearerOnly"] || false
|
|
48
48
|
client.consent_required = hash["consentRequired"] || false
|
|
49
49
|
client.standard_flow_enabled = hash["standardFlowEnabled"] || false
|
|
@@ -60,7 +60,6 @@ module KeycloakAdmin
|
|
|
60
60
|
client.authentication_flow_binding_overrides = hash["authenticationFlowBindingOverrides"] || {}
|
|
61
61
|
client.full_scope_allowed = hash["fullScopeAllowed"] || false
|
|
62
62
|
client.node_re_registration_timeout = hash["nodeReRegistrationTimeout"] || -1
|
|
63
|
-
client.attributes = hash["attributes"]
|
|
64
63
|
client.protocol_mappers = (hash["protocolMappers"] || []).map { |protocol_mapper_hash| ProtocolMapperRepresentation.from_hash(protocol_mapper_hash) }
|
|
65
64
|
client.default_client_scopes = hash["defaultClientScopes"] || []
|
|
66
65
|
client.optional_client_scopes = hash["optionalClientScopes"] || []
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
class OrganizationRepresentation < Representation
|
|
3
4
|
attr_accessor :id,
|
|
@@ -9,7 +10,6 @@ module KeycloakAdmin
|
|
|
9
10
|
:attributes,
|
|
10
11
|
:domains,
|
|
11
12
|
:members,
|
|
12
|
-
:attributes,
|
|
13
13
|
:identity_providers
|
|
14
14
|
|
|
15
15
|
def self.from_hash(hash)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require "json"
|
|
2
3
|
require_relative "camel_json"
|
|
3
4
|
|
|
@@ -5,14 +6,15 @@ class Representation
|
|
|
5
6
|
include ::KeycloakAdmin::CamelJson
|
|
6
7
|
|
|
7
8
|
def as_json(options=nil)
|
|
8
|
-
|
|
9
|
+
instance_variables.each_with_object({}) do |ivar, hash|
|
|
10
|
+
val = instance_variable_get(ivar)
|
|
11
|
+
hash[ivar.to_s[1..-1]] = val unless val.nil?
|
|
12
|
+
end
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
def to_json(options=nil)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
camelized_hash[camelize(key, false)] = snaked_hash[key]
|
|
15
|
-
camelized_hash
|
|
16
|
+
as_json(options).each_with_object({}) do |(key, val), hash|
|
|
17
|
+
hash[camelize(key, false)] = val
|
|
16
18
|
end.to_json(options)
|
|
17
19
|
end
|
|
18
20
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
class SessionRepresentation < Representation
|
|
3
4
|
attr_accessor :id,
|
|
@@ -6,7 +7,7 @@ module KeycloakAdmin
|
|
|
6
7
|
:ip_address,
|
|
7
8
|
:start,
|
|
8
9
|
:last_access,
|
|
9
|
-
:remember_me
|
|
10
|
+
:remember_me
|
|
10
11
|
|
|
11
12
|
def self.from_hash(hash)
|
|
12
13
|
rep = new
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module KeycloakAdmin
|
|
2
3
|
class BaseRoleContainingResource
|
|
4
|
+
include PathEncoding
|
|
5
|
+
|
|
3
6
|
attr_reader :resource_id
|
|
4
7
|
|
|
5
8
|
def initialize(configuration, realm_client, resource_id)
|
|
@@ -14,7 +17,7 @@ module KeycloakAdmin
|
|
|
14
17
|
end
|
|
15
18
|
|
|
16
19
|
def resource_url
|
|
17
|
-
"#{@realm_client.realm_admin_url}/#{resources_name}/#{@resource_id}"
|
|
20
|
+
"#{@realm_client.realm_admin_url}/#{resources_name}/#{encode_segment(@resource_id)}"
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
def client_role_mappings(client_id)
|