keycloak-admin 0.7.4 → 0.7.9
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 +25 -1
- data/Gemfile.lock +7 -5
- data/README.md +62 -32
- data/lib/keycloak-admin.rb +2 -1
- data/lib/keycloak-admin/client/configurable_token_client.rb +12 -7
- data/lib/keycloak-admin/client/user_client.rb +86 -8
- data/lib/keycloak-admin/representation/federated_identity_representation.rb +15 -0
- data/lib/keycloak-admin/representation/user_representation.rb +20 -13
- data/lib/keycloak-admin/version.rb +1 -1
- data/spec/client/user_client_spec.rb +38 -1
- data/spec/representation/user_representation_spec.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ddc2a67d3273ab4353daeb48dce261f5ba27a310fa91e9947e751da86d55a124
|
|
4
|
+
data.tar.gz: 5850f80b6f5c1f76ade40a92bba444559fcc1f637bee0eaf1cb4b917cbfd7f4c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 210d92708eb39e0f221cd54f7c5d1fec917f8a1cab5bafb6ec1b1f706b60e634acf55bd38396bf5017ac95eef4aaed2d3892700ec9cbcc84757128ed02f2d46f
|
|
7
|
+
data.tar.gz: 45e19fa08576cb1f468f0fc9dd6841da93e0bafe91002361ad78610637a41e438bfc7e7a04f5741eab87bc161cab4982b7d9fd88a482862ede548c03b2e3c287
|
data/CHANGELOG.md
CHANGED
|
@@ -5,13 +5,37 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.9] - 2020-10-22
|
|
9
|
+
|
|
10
|
+
* Extend `search` function to use complex queries (thanks to @hobbypunk90)
|
|
11
|
+
|
|
12
|
+
## [0.7.8] - 2020-10-15
|
|
13
|
+
|
|
14
|
+
* Bug: `rest_client_options` default value does not match the documentation (was `nil` by default, should be `{}`)
|
|
15
|
+
* Update documentation about client setup (based on Keycloak 11)
|
|
16
|
+
|
|
17
|
+
## [0.7.7] - 2020-07-10
|
|
18
|
+
|
|
19
|
+
* Fix: `Replace request method shorthand with .execute for proper RestClient option support` (thanks to @RomanHargrave)
|
|
20
|
+
* When sending action emails, add lifespan as an optional parameter (thanks to @hobbypunk90)
|
|
21
|
+
|
|
22
|
+
## [0.7.6] - 2020-06-22
|
|
23
|
+
|
|
24
|
+
Thanks to @hobbypunk90
|
|
25
|
+
* Support for action emails and send forgot passsword mail
|
|
26
|
+
|
|
27
|
+
## [0.7.5] - 2020-03-28
|
|
28
|
+
|
|
29
|
+
Thanks to @RomanHargrave
|
|
30
|
+
* Support for working with federated identity provider (broker) links
|
|
31
|
+
|
|
8
32
|
## [0.7.4] - 2019-10-17
|
|
9
33
|
|
|
10
34
|
* Support for Rails 6
|
|
11
35
|
|
|
12
36
|
## [0.7.3] - 2019-07-11
|
|
13
37
|
|
|
14
|
-
Thanks to @cederigo
|
|
38
|
+
Thanks to @cederigo:
|
|
15
39
|
* For a given user, get her list of groups
|
|
16
40
|
|
|
17
41
|
## [0.7.2] - 2019-06-17
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
keycloak-admin (0.7.
|
|
4
|
+
keycloak-admin (0.7.9)
|
|
5
5
|
http-cookie (~> 1.0, >= 1.0.3)
|
|
6
6
|
rest-client (~> 2.0)
|
|
7
7
|
|
|
@@ -12,13 +12,15 @@ GEM
|
|
|
12
12
|
diff-lcs (1.3)
|
|
13
13
|
domain_name (0.5.20190701)
|
|
14
14
|
unf (>= 0.0.5, < 1.0.0)
|
|
15
|
+
http-accept (1.7.0)
|
|
15
16
|
http-cookie (1.0.3)
|
|
16
17
|
domain_name (~> 0.5)
|
|
17
|
-
mime-types (3.
|
|
18
|
+
mime-types (3.3.1)
|
|
18
19
|
mime-types-data (~> 3.2015)
|
|
19
|
-
mime-types-data (3.
|
|
20
|
+
mime-types-data (3.2020.0512)
|
|
20
21
|
netrc (0.11.0)
|
|
21
|
-
rest-client (2.0
|
|
22
|
+
rest-client (2.1.0)
|
|
23
|
+
http-accept (>= 1.7.0, < 2.0)
|
|
22
24
|
http-cookie (>= 1.0.2, < 2.0)
|
|
23
25
|
mime-types (>= 1.16, < 4.0)
|
|
24
26
|
netrc (~> 0.8)
|
|
@@ -37,7 +39,7 @@ GEM
|
|
|
37
39
|
rspec-support (3.7.0)
|
|
38
40
|
unf (0.1.4)
|
|
39
41
|
unf_ext
|
|
40
|
-
unf_ext (0.0.7.
|
|
42
|
+
unf_ext (0.0.7.7)
|
|
41
43
|
|
|
42
44
|
PLATFORMS
|
|
43
45
|
ruby
|
data/README.md
CHANGED
|
@@ -12,37 +12,59 @@ This gem *does not* require Rails.
|
|
|
12
12
|
For example, using `bundle`, add this line to your Gemfile.
|
|
13
13
|
|
|
14
14
|
```ruby
|
|
15
|
-
gem "keycloak-admin", "0.7.
|
|
15
|
+
gem "keycloak-admin", "0.7.9"
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Login
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
20
|
+
To login on Keycloak's Admin API, you first need to setup a client.
|
|
21
|
+
|
|
22
|
+
Go to your realm administration page and open `Clients`. Then, click on the `Create` button.
|
|
23
|
+
On the first screen, enter:
|
|
24
|
+
* `Client ID`: _e.g. my-app-admin-client_
|
|
25
|
+
* `Client Protocol`: select `openid-connect`
|
|
26
|
+
* `Root URL`: let it blank
|
|
27
|
+
|
|
28
|
+
The next screen must be configured depending on how you want to authenticate:
|
|
29
|
+
* `username/password` with a user of the realm
|
|
30
|
+
* `Direct Access Grants` with a service account
|
|
31
|
+
|
|
32
|
+
### Login with username/password (realm user)
|
|
33
|
+
|
|
34
|
+
* In Keycloak, during the client setup:
|
|
35
|
+
* `Access Type`: `public` or `confidential`
|
|
36
|
+
* `Service Accounts Enabled` (when `confidential`): `false`
|
|
37
|
+
* After saving your client, if you have chosen a `confidential` client, go to `Credentials` tab and copy the `Client Secret`
|
|
38
|
+
|
|
39
|
+
* In Keycloak, create a dedicated user (and her credentials):
|
|
40
|
+
* Go to `Users`
|
|
41
|
+
* Click on the `Add user` button
|
|
42
|
+
* Setup her mandatory information, depending on your realm's configuration
|
|
43
|
+
* On the `Credentials` tab, create her a password (toggle off `Temporary`)
|
|
44
|
+
|
|
45
|
+
* In this gem's configuration (see Section `Configuration`):
|
|
46
|
+
* Setup `username` and `password` according to your user's configuration
|
|
47
|
+
* Setup `client_id` with your `Client ID` (_e.g. my-app-admin-client_)
|
|
48
|
+
* If your client is `confidential`, copy its Client Secret to `client_secret`
|
|
49
|
+
|
|
50
|
+
### Login with `Direct Access Grants` (Service account)
|
|
51
|
+
|
|
52
|
+
Using a service account to use the REST Admin API does not require to create a dedicated user (https://www.keycloak.org/docs/latest/server_admin/#_service_accounts).
|
|
53
|
+
|
|
54
|
+
* In Keycloak, during the client setup:
|
|
55
|
+
* `Access Type`: `confidential`
|
|
56
|
+
* `Service Accounts Enabled` (when `confidential`): `true`
|
|
57
|
+
* `Standard Flow Enabled`: `false`
|
|
58
|
+
* `Implicit Flow Enabled`: `false`
|
|
59
|
+
* `Direct Access Grants Enabled`: `true`
|
|
60
|
+
* After saving this client
|
|
61
|
+
* open the `Service Account Roles` and add relevant `realm-management.` client's roles. For instance: `view-users` if you want to search for users using this gem.
|
|
62
|
+
* open the `Credentials` tab and copy the `Client Secret`
|
|
63
|
+
|
|
64
|
+
* In this gem's configuration (see Section `Configuration`):
|
|
44
65
|
* Set `use_service_account` to `true`
|
|
45
|
-
* Setup `
|
|
66
|
+
* Setup `client_id` with your `Client ID` (_e.g. my-app-admin-client_)
|
|
67
|
+
* Copy its Client Secret to `client_secret`
|
|
46
68
|
|
|
47
69
|
## Configuration
|
|
48
70
|
|
|
@@ -69,7 +91,8 @@ All options have a default value. However, all of them can be changed in your in
|
|
|
69
91
|
|
|
70
92
|
| Option | Default Value | Type | Required? | Description | Example |
|
|
71
93
|
| ---- | ----- | ------ | ----- | ------ | ----- |
|
|
72
|
-
| `server_url` | `nil
|
|
94
|
+
| `server_url` | `nil` | String | Required | The base url where your Keycloak server is located (a URL that starts with `http` and that ends with `/auth`). This value can be retrieved in your Keycloak client configuration. | `http://auth:8080/auth`
|
|
95
|
+
| `server_domain` | `nil`| String | Required | Public domain that identify your authentication cookies. | `auth.service.io` |
|
|
73
96
|
| `client_realm_name` | `""`| String | Required | Name of the realm that contains the admin client. | `master` |
|
|
74
97
|
| `client_id` | `admin-cli`| String | Required | Client that should be used to access admin capabilities. | `api-cli` |
|
|
75
98
|
| `client_secret` | `nil`| String | Optional | If your client is `confidential`, this parameter must be specified. | `4e3c481c-f823-4a6a-b8a7-bf8c86e3eac3` |
|
|
@@ -97,6 +120,9 @@ All options have a default value. However, all of them can be changed in your in
|
|
|
97
120
|
* Get list of client role mappings for a user/group
|
|
98
121
|
* Save client role mappings for a user/group
|
|
99
122
|
* Save realm-level role mappings for a user/group
|
|
123
|
+
* Link/Unlink users to federated identity provider brokers
|
|
124
|
+
* Execute actions emails
|
|
125
|
+
* Send forgot passsword mail
|
|
100
126
|
|
|
101
127
|
### Get an access token
|
|
102
128
|
|
|
@@ -119,10 +145,18 @@ KeycloakAdmin.realm("a_realm").users.get(user_id)
|
|
|
119
145
|
|
|
120
146
|
Returns an array of `KeycloakAdmin::UserRepresentation`.
|
|
121
147
|
|
|
148
|
+
According to [the documentation](https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_users_resource):
|
|
149
|
+
* When providing a `String` parameter, this produces an arbitrary search string
|
|
150
|
+
* When providing a `Hash`, you can search for specific field (_e.g_ an email)
|
|
151
|
+
|
|
122
152
|
```ruby
|
|
123
153
|
KeycloakAdmin.realm("a_realm").users.search("a_username_or_an_email")
|
|
124
154
|
```
|
|
125
155
|
|
|
156
|
+
```ruby
|
|
157
|
+
KeycloakAdmin.realm("a_realm").users.search({ email: "john@doe.com" })
|
|
158
|
+
```
|
|
159
|
+
|
|
126
160
|
### List all users in a realm
|
|
127
161
|
|
|
128
162
|
Returns an array of `KeycloakAdmin::UserRepresentation`.
|
|
@@ -340,8 +374,4 @@ From the `keycloak-admin-api` directory:
|
|
|
340
374
|
```
|
|
341
375
|
$ docker build . -t keycloak-admin:test
|
|
342
376
|
$ docker run -v `pwd`:/usr/src/app/ keycloak-admin:test bundle exec rspec spec
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
## Future work
|
|
346
|
-
|
|
347
|
-
* Allow authentication using JWT assertions
|
|
377
|
+
```
|
data/lib/keycloak-admin.rb
CHANGED
|
@@ -21,6 +21,7 @@ require_relative "keycloak-admin/representation/impersonation_representation"
|
|
|
21
21
|
require_relative "keycloak-admin/representation/credential_representation"
|
|
22
22
|
require_relative "keycloak-admin/representation/realm_representation"
|
|
23
23
|
require_relative "keycloak-admin/representation/role_representation"
|
|
24
|
+
require_relative "keycloak-admin/representation/federated_identity_representation"
|
|
24
25
|
require_relative "keycloak-admin/representation/user_representation"
|
|
25
26
|
require_relative "keycloak-admin/resource/base_role_containing_resource"
|
|
26
27
|
require_relative "keycloak-admin/resource/group_resource"
|
|
@@ -54,7 +55,7 @@ module KeycloakAdmin
|
|
|
54
55
|
config.use_service_account = true
|
|
55
56
|
config.username = nil
|
|
56
57
|
config.password = nil
|
|
57
|
-
config.rest_client_options =
|
|
58
|
+
config.rest_client_options = {}
|
|
58
59
|
end
|
|
59
60
|
end
|
|
60
61
|
|
|
@@ -16,13 +16,18 @@ module KeycloakAdmin
|
|
|
16
16
|
|
|
17
17
|
def exchange_with(user_access_token, token_lifespan_in_seconds)
|
|
18
18
|
response = execute_http do
|
|
19
|
-
RestClient.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
RestClient::Request.execute(
|
|
20
|
+
@configuration.rest_client_options.merge(
|
|
21
|
+
method: :post,
|
|
22
|
+
url: token_url,
|
|
23
|
+
payload: { tokenLifespanInSeconds: token_lifespan_in_seconds }.to_json,
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: "Bearer #{user_access_token}",
|
|
26
|
+
content_type: :json,
|
|
27
|
+
accept: :json
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
)
|
|
26
31
|
end
|
|
27
32
|
TokenRepresentation.from_json(response.body)
|
|
28
33
|
end
|
|
@@ -21,7 +21,14 @@ module KeycloakAdmin
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def update(user_id, user_representation_body)
|
|
24
|
-
RestClient.
|
|
24
|
+
RestClient::Request.execute(
|
|
25
|
+
@configuration.rest_client_options.merge(
|
|
26
|
+
method: :put,
|
|
27
|
+
url: users_url(user_id),
|
|
28
|
+
payload: user_representation_body.to_json,
|
|
29
|
+
headers: headers
|
|
30
|
+
)
|
|
31
|
+
)
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
def get(user_id)
|
|
@@ -31,8 +38,22 @@ module KeycloakAdmin
|
|
|
31
38
|
UserRepresentation.from_hash(JSON.parse(response))
|
|
32
39
|
end
|
|
33
40
|
|
|
41
|
+
##
|
|
42
|
+
# Query can be a string or a hash.
|
|
43
|
+
# * String: It's used as search query
|
|
44
|
+
# * Hash: Used for complex search queries.
|
|
45
|
+
# For its documentation see: https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_users_resource
|
|
46
|
+
##
|
|
34
47
|
def search(query)
|
|
35
|
-
derived_headers =
|
|
48
|
+
derived_headers = case query
|
|
49
|
+
when String
|
|
50
|
+
headers.merge({params: { search: query }})
|
|
51
|
+
when Hash
|
|
52
|
+
headers.merge({params: query })
|
|
53
|
+
else
|
|
54
|
+
headers
|
|
55
|
+
end
|
|
56
|
+
|
|
36
57
|
response = execute_http do
|
|
37
58
|
RestClient::Resource.new(users_url, @configuration.rest_client_options).get(derived_headers)
|
|
38
59
|
end
|
|
@@ -59,11 +80,26 @@ module KeycloakAdmin
|
|
|
59
80
|
|
|
60
81
|
def update_password(user_id, new_password)
|
|
61
82
|
execute_http do
|
|
62
|
-
RestClient.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
RestClient::Request.execute(
|
|
84
|
+
@configuration.rest_client_options.merge(
|
|
85
|
+
method: :put,
|
|
86
|
+
url: reset_password_url(user_id),
|
|
87
|
+
payload: { type: 'password', value: new_password, temporary: false }.to_json,
|
|
88
|
+
headers: headers
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
user_id
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def forgot_password(user_id, lifespan=nil)
|
|
96
|
+
execute_actions_email(user_id, ["UPDATE_PASSWORD"], lifespan)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def execute_actions_email(user_id, actions=[], lifespan=nil)
|
|
100
|
+
execute_http do
|
|
101
|
+
lifespan_param = lifespan.nil? ? "" : "lifespan=#{lifespan.seconds}"
|
|
102
|
+
RestClient.put("#{execute_actions_email_url(user_id)}?#{lifespan_param}", actions.to_json, headers)
|
|
67
103
|
end
|
|
68
104
|
user_id
|
|
69
105
|
end
|
|
@@ -71,7 +107,14 @@ module KeycloakAdmin
|
|
|
71
107
|
def impersonate(user_id)
|
|
72
108
|
impersonation = get_redirect_impersonation(user_id)
|
|
73
109
|
response = execute_http do
|
|
74
|
-
RestClient.
|
|
110
|
+
RestClient::Request.execute(
|
|
111
|
+
@configuration.rest_client_options.merge(
|
|
112
|
+
method: :post,
|
|
113
|
+
url: impersonation.impersonation_url,
|
|
114
|
+
payload: impersonation.body.to_json,
|
|
115
|
+
headers: impersonation.headers
|
|
116
|
+
)
|
|
117
|
+
)
|
|
75
118
|
end
|
|
76
119
|
ImpersonationRepresentation.from_response(response, @configuration.server_domain)
|
|
77
120
|
end
|
|
@@ -80,6 +123,30 @@ module KeycloakAdmin
|
|
|
80
123
|
ImpersonationRedirectionRepresentation.from_url(impersonation_url(user_id), headers)
|
|
81
124
|
end
|
|
82
125
|
|
|
126
|
+
def link_idp(user_id, idp_id, idp_user_id, idp_username)
|
|
127
|
+
fed_id_rep = FederatedIdentityRepresentation.new
|
|
128
|
+
fed_id_rep.user_id = idp_user_id
|
|
129
|
+
fed_id_rep.user_name = idp_username
|
|
130
|
+
fed_id_rep.identity_provider = idp_id
|
|
131
|
+
|
|
132
|
+
execute_http do
|
|
133
|
+
RestClient::Request.execute(
|
|
134
|
+
@configuration.rest_client_options.merge(
|
|
135
|
+
method: :post,
|
|
136
|
+
url: federated_identity_url(user_id, idp_id),
|
|
137
|
+
payload: fed_id_rep.to_json,
|
|
138
|
+
headers: headers
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def unlink_idp(user_id, idp_id)
|
|
145
|
+
execute_http do
|
|
146
|
+
RestClient::Resource.new(federated_identity_url(user_id, idp_id), @configuration.rest_client_options).delete(headers)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
83
150
|
def users_url(id=nil)
|
|
84
151
|
if id
|
|
85
152
|
"#{@realm_client.realm_admin_url}/users/#{id}"
|
|
@@ -93,6 +160,11 @@ module KeycloakAdmin
|
|
|
93
160
|
"#{users_url(user_id)}/reset-password"
|
|
94
161
|
end
|
|
95
162
|
|
|
163
|
+
def execute_actions_email_url(user_id)
|
|
164
|
+
raise ArgumentError.new("user_id must be defined") if user_id.nil?
|
|
165
|
+
"#{users_url(user_id)}/execute-actions-email"
|
|
166
|
+
end
|
|
167
|
+
|
|
96
168
|
def groups_url(user_id)
|
|
97
169
|
raise ArgumentError.new("user_id must be defined") if user_id.nil?
|
|
98
170
|
"#{users_url(user_id)}/groups"
|
|
@@ -103,6 +175,12 @@ module KeycloakAdmin
|
|
|
103
175
|
"#{users_url(user_id)}/impersonation"
|
|
104
176
|
end
|
|
105
177
|
|
|
178
|
+
def federated_identity_url(user_id, identity_provider)
|
|
179
|
+
raise ArgumentError.new("user_id must be defined") if user_id.nil?
|
|
180
|
+
raise ArgumentError.new("identity_provider must be defined") if identity_provider.nil?
|
|
181
|
+
"#{users_url(user_id)}/federated-identity/#{identity_provider}"
|
|
182
|
+
end
|
|
183
|
+
|
|
106
184
|
private
|
|
107
185
|
|
|
108
186
|
def build(username, email, password, email_verified, locale)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module KeycloakAdmin
|
|
2
|
+
class FederatedIdentityRepresentation < Representation
|
|
3
|
+
attr_accessor :identity_provider,
|
|
4
|
+
:user_id,
|
|
5
|
+
:user_name
|
|
6
|
+
|
|
7
|
+
def self.from_hash(hash)
|
|
8
|
+
rep = new
|
|
9
|
+
rep.identity_provider = hash['identityProvider']
|
|
10
|
+
rep.user_id = hash['userId']
|
|
11
|
+
rep.user_name = hash['userName']
|
|
12
|
+
rep
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -10,21 +10,23 @@ module KeycloakAdmin
|
|
|
10
10
|
:email_verified,
|
|
11
11
|
:first_name,
|
|
12
12
|
:last_name,
|
|
13
|
-
:credentials
|
|
13
|
+
:credentials,
|
|
14
|
+
:federated_identities
|
|
14
15
|
|
|
15
16
|
def self.from_hash(hash)
|
|
16
|
-
user
|
|
17
|
-
user.id
|
|
18
|
-
user.created_timestamp
|
|
19
|
-
user.origin
|
|
20
|
-
user.username
|
|
21
|
-
user.email
|
|
22
|
-
user.enabled
|
|
23
|
-
user.email_verified
|
|
24
|
-
user.first_name
|
|
25
|
-
user.last_name
|
|
26
|
-
user.attributes
|
|
27
|
-
user.credentials
|
|
17
|
+
user = new
|
|
18
|
+
user.id = hash["id"]
|
|
19
|
+
user.created_timestamp = hash["createdTimestamp"]
|
|
20
|
+
user.origin = hash["origin"]
|
|
21
|
+
user.username = hash["username"]
|
|
22
|
+
user.email = hash["email"]
|
|
23
|
+
user.enabled = hash["enabled"]
|
|
24
|
+
user.email_verified = hash["emailVerified"]
|
|
25
|
+
user.first_name = hash["firstName"]
|
|
26
|
+
user.last_name = hash["lastName"]
|
|
27
|
+
user.attributes = hash["attributes"]
|
|
28
|
+
user.credentials = hash["credentials"]&.map{ |hash| CredentialRepresentation.from_hash(hash) } || []
|
|
29
|
+
user.federated_identities = hash["federatedIdentities"]&.map { |hash| FederatedIdentityRepresentation.from_hash(hash) } || []
|
|
28
30
|
user
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -32,5 +34,10 @@ module KeycloakAdmin
|
|
|
32
34
|
@credentials ||= []
|
|
33
35
|
@credentials.push(credential_representation)
|
|
34
36
|
end
|
|
37
|
+
|
|
38
|
+
def add_federated_identity(federated_identity_representation)
|
|
39
|
+
@federated_identities ||= []
|
|
40
|
+
@federated_identities.push(federated_identity_representation)
|
|
41
|
+
end
|
|
35
42
|
end
|
|
36
43
|
end
|
|
@@ -72,6 +72,31 @@ RSpec.describe KeycloakAdmin::TokenClient do
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
describe "#execute_actions_email_url" do
|
|
76
|
+
let(:realm_name) { "valid-realm" }
|
|
77
|
+
let(:user_id) { nil }
|
|
78
|
+
|
|
79
|
+
before(:each) do
|
|
80
|
+
@client = KeycloakAdmin.realm(realm_name).users
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context "when user_id is not defined" do
|
|
84
|
+
let(:user_id) { nil }
|
|
85
|
+
it "raises an error" do
|
|
86
|
+
expect {
|
|
87
|
+
@client.execute_actions_email_url(user_id)
|
|
88
|
+
}.to raise_error(ArgumentError)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "when user_id is defined" do
|
|
93
|
+
let(:user_id) { 42 }
|
|
94
|
+
it "return a proper url" do
|
|
95
|
+
expect(@client.execute_actions_email_url(user_id)).to eq "http://auth.service.io/auth/admin/realms/valid-realm/users/42/execute-actions-email"
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
75
100
|
describe "#impersonation_url" do
|
|
76
101
|
let(:realm_name) { "valid-realm" }
|
|
77
102
|
let(:user_id) { nil }
|
|
@@ -167,12 +192,24 @@ RSpec.describe KeycloakAdmin::TokenClient do
|
|
|
167
192
|
allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '[{"username":"test_username","createdTimestamp":1559347200}]'
|
|
168
193
|
end
|
|
169
194
|
|
|
170
|
-
it "finds a user" do
|
|
195
|
+
it "finds a user using a string" do
|
|
171
196
|
users = @user_client.search("test_username")
|
|
172
197
|
expect(users.length).to eq 1
|
|
173
198
|
expect(users[0].username).to eq "test_username"
|
|
174
199
|
end
|
|
175
200
|
|
|
201
|
+
it "finds a user using nil does not fail" do
|
|
202
|
+
users = @user_client.search(nil)
|
|
203
|
+
expect(users.length).to eq 1
|
|
204
|
+
expect(users[0].username).to eq "test_username"
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "finds a user using a hash" do
|
|
208
|
+
users = @user_client.search({ search: "test_username"})
|
|
209
|
+
expect(users.length).to eq 1
|
|
210
|
+
expect(users[0].username).to eq "test_username"
|
|
211
|
+
end
|
|
212
|
+
|
|
176
213
|
it "passes rest client options" do
|
|
177
214
|
rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
|
|
178
215
|
allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
|
|
@@ -9,7 +9,7 @@ RSpec.describe KeycloakAdmin::UserRepresentation do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
it "can convert to json" do
|
|
12
|
-
expect(@user.to_json).to eq '{"id":null,"createdTimestamp":1559836000,"origin":null,"username":"test_username","email":null,"enabled":true,"emailVerified":null,"firstName":null,"lastName":null,"attributes":null,"credentials":[]}'
|
|
12
|
+
expect(@user.to_json).to eq '{"id":null,"createdTimestamp":1559836000,"origin":null,"username":"test_username","email":null,"enabled":true,"emailVerified":null,"firstName":null,"lastName":null,"attributes":null,"credentials":[],"federatedIdentities":[]}'
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: keycloak-admin
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lorent Lempereur
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-10-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: http-cookie
|
|
@@ -103,6 +103,7 @@ files:
|
|
|
103
103
|
- lib/keycloak-admin/representation/camel_json.rb
|
|
104
104
|
- lib/keycloak-admin/representation/client_representation.rb
|
|
105
105
|
- lib/keycloak-admin/representation/credential_representation.rb
|
|
106
|
+
- lib/keycloak-admin/representation/federated_identity_representation.rb
|
|
106
107
|
- lib/keycloak-admin/representation/group_representation.rb
|
|
107
108
|
- lib/keycloak-admin/representation/impersonation_redirection_representation.rb
|
|
108
109
|
- lib/keycloak-admin/representation/impersonation_representation.rb
|
|
@@ -150,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
150
151
|
- !ruby/object:Gem::Version
|
|
151
152
|
version: '0'
|
|
152
153
|
requirements: []
|
|
153
|
-
rubygems_version: 3.0.
|
|
154
|
+
rubygems_version: 3.0.3
|
|
154
155
|
signing_key:
|
|
155
156
|
specification_version: 4
|
|
156
157
|
summary: Keycloak Admin REST API client written in Ruby
|