keycloak-admin 1.1.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 140b6a3bb680503f4bac8336250974b930535ef270f66b56b488ad78e182cd6b
4
- data.tar.gz: 45c9d2ed7af63d6eaf027eebb4a6a9309d115d1fea88df9d8b4bb5c0d14ec7cc
3
+ metadata.gz: 75a9e29c443612983e789a4d2d38d050908a0239fd4b74bca5f5d722234ef940
4
+ data.tar.gz: e0bf740884bb1da5bf3c63032f6349e46f98ce56f1b06f0ae62dcb96eb324bb7
5
5
  SHA512:
6
- metadata.gz: da197ebef3a7bc8fc82a95258eb684d007fbb69d48b62f6f19afd510fbbce11b30ac0c98f3b0731ebc56556311330707360a72f0505c9021d7f34d799a045534
7
- data.tar.gz: e77461558697bbe7c372973673a3e58d9530720da6db2eaa76b79b1616e06ad05148cf843bd3c23a9d15a6fa55e27ac8988fccea776d593fd96e5f1130b6c0e1
6
+ metadata.gz: 1cc1adf071a240af23ace33f0f48d3b4c9cee0868dc4e50acab30d900bc0575fd4784bd725869dff58e79c053e4b6505376569855fbdb647bf929b8d82190277
7
+ data.tar.gz: e34ae74e3096db9fa6ac6c92370eed71e23e25a4d896a98eed1afb68cfeb422d66ad99eb5d4a02460bd7fa3a6b57b2c6b351bfb42d4adb7fcdab70fc838f4825
data/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ 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
+ ## [1.1.2] - 2024-05-22
9
+
10
+ * Add group endpoints (get, children, delete), support for group attributes (thanks to @mkrawc)
11
+ * GroupClient#save method now can update an existing group (thanks to @mkrawc)
12
+ * RoleClient#save method now can update an existing role (thanks to @mkrawc)
13
+
14
+ ## [1.1.1] - 2024-01-21
15
+
16
+ * Add/List realm-role/s to a group, Allow role-names with spaces, List groups assigned to role (thanks to @LiquidMagical)
17
+
8
18
  ## [1.1.0] - 2023-10-03
9
19
 
10
20
  * Search for groups with parameters (thanks to @@tlloydthwaites)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keycloak-admin (1.1.0)
4
+ keycloak-admin (1.1.2)
5
5
  http-cookie (~> 1.0, >= 1.0.3)
6
6
  rest-client (~> 2.0)
7
7
 
@@ -9,15 +9,14 @@ GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
11
  byebug (11.1.3)
12
- diff-lcs (1.5.0)
13
- domain_name (0.5.20190701)
14
- unf (>= 0.0.5, < 1.0.0)
12
+ diff-lcs (1.5.1)
13
+ domain_name (0.6.20240107)
15
14
  http-accept (1.7.0)
16
15
  http-cookie (1.0.5)
17
16
  domain_name (~> 0.5)
18
- mime-types (3.5.1)
17
+ mime-types (3.5.2)
19
18
  mime-types-data (~> 3.2015)
20
- mime-types-data (3.2023.0808)
19
+ mime-types-data (3.2024.0507)
21
20
  netrc (0.11.0)
22
21
  rest-client (2.1.0)
23
22
  http-accept (>= 1.7.0, < 2.0)
@@ -28,18 +27,15 @@ GEM
28
27
  rspec-core (~> 3.12.0)
29
28
  rspec-expectations (~> 3.12.0)
30
29
  rspec-mocks (~> 3.12.0)
31
- rspec-core (3.12.2)
30
+ rspec-core (3.12.3)
32
31
  rspec-support (~> 3.12.0)
33
- rspec-expectations (3.12.3)
32
+ rspec-expectations (3.12.4)
34
33
  diff-lcs (>= 1.2.0, < 2.0)
35
34
  rspec-support (~> 3.12.0)
36
- rspec-mocks (3.12.6)
35
+ rspec-mocks (3.12.7)
37
36
  diff-lcs (>= 1.2.0, < 2.0)
38
37
  rspec-support (~> 3.12.0)
39
- rspec-support (3.12.1)
40
- unf (0.1.4)
41
- unf_ext
42
- unf_ext (0.0.8.2)
38
+ rspec-support (3.12.2)
43
39
 
44
40
  PLATFORMS
45
41
  ruby
data/README.md CHANGED
@@ -12,7 +12,7 @@ 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", "1.0.24"
15
+ gem "keycloak-admin", "1.1.2"
16
16
  ```
17
17
 
18
18
  ## Login
@@ -80,7 +80,9 @@ KeycloakAdmin.configure do |config|
80
80
  config.username = ENV["KEYCLOAK_ADMIN_USER"]
81
81
  config.password = ENV["KEYCLOAK_ADMIN_PASSWORD"]
82
82
  config.logger = Rails.logger
83
- config.rest_client_options = { verify_ssl: OpenSSL::SSL::VERIFY_NONE }
83
+
84
+ # You configure RestClient to your liking – see https://github.com/rest-client/rest-client/blob/master/lib/restclient/request.rb for available options.
85
+ config.rest_client_options = { timeout: 5 }
84
86
  end
85
87
  ```
86
88
  This example is autoloaded in a Rails environment.
@@ -100,7 +102,7 @@ All options have a default value. However, all of them can be changed in your in
100
102
  | `username` | `nil`| String | Optional | Username to access the Admin REST API. Recommended if `user_service_account` is set to `false`. | `mummy` |
101
103
  | `password` | `nil`| String | Optional | Clear password to access the Admin REST API. Recommended if `user_service_account` is set to `false`. | `bobby` |
102
104
  | `logger` | `Logger.new(STDOUT)`| Logger | Optional | The logger used by `keycloak-admin` | `Rails.logger` | 
103
- | `rest_client_options` | `{}`| Hash | Optional | Options to pass to `RestClient` | `{ verify_ssl: OpenSSL::SSL::VERIFY_NONE }` | 
105
+ | `rest_client_options` | `{}`| Hash | Optional | Options to pass to `RestClient` | `{ timeout: 5 }` | 
104
106
 
105
107
 
106
108
  ## Use Cases
@@ -120,6 +122,8 @@ All options have a default value. However, all of them can be changed in your in
120
122
  * Get list of realms, save/update/delete a realm
121
123
  * Get list of client role mappings for a user/group
122
124
  * Get list of members of a group
125
+ * Get list of groups that have a specific role assigned
126
+ * Get list of realm-roles assigned to a group, add a realm-role to a group
123
127
  * Save client role mappings for a user/group
124
128
  * Save realm-level role mappings for a user/group
125
129
  * Add a Group on a User
@@ -185,10 +189,15 @@ If you want to update its entire entity. To update some specific attributes, pro
185
189
 
186
190
  ```ruby
187
191
  KeycloakAdmin.realm("a_realm").users.update("05c135c6-5ad8-4e17-b1fa-635fc089fd71", {
188
- email: "hello@gmail.com"
192
+ email: "hello@gmail.com",
193
+ username: "hello",
194
+ first_name: "Jean",
195
+ last_name: "Dupond"
189
196
  })
190
197
  ```
191
198
 
199
+ Attention point: Since Keycloak 24.0.4, when updating a user, all the writable profile attributes must be passed, otherwise they will be removed. (https://www.keycloak.org/docs/24.0.4/upgrading/)
200
+
192
201
  ### Delete a user
193
202
 
194
203
  ```ruby
@@ -367,6 +376,30 @@ You can specify paging with `first` and `max`:
367
376
  KeycloakAdmin.realm("a_realm").group("group_id").members(first:0, max:100)
368
377
  ```
369
378
 
379
+ ### Get list of groups that have a specific role assigned
380
+
381
+ Returns an array of `KeycloakAdmin::GroupRepresentation`
382
+
383
+ ```ruby
384
+ KeycloakAdmin.realm("a_realm").roles.list_groups("role_name")
385
+ ```
386
+
387
+ ### Get list of realm-roles assigned to a group
388
+
389
+ Returns an array of `KeycloakAdmin::RoleRepresentation`
390
+
391
+ ```ruby
392
+ KeycloakAdmin.realm("a_realm").groups.get_realm_level_roles("group_id")
393
+ ```
394
+
395
+ ### Add a realm-role to a group
396
+
397
+ Returns added `KeycloakAdmin::RoleRepresentation`
398
+
399
+ ```ruby
400
+ KeycloakAdmin.realm("a_realm").groups.add_realm_level_role_name!("group_id", "role_name")
401
+ ```
402
+
370
403
  ### Get list of roles in a realm
371
404
 
372
405
  Returns an array of `KeycloakAdmin::RoleRepresentation`.
@@ -6,6 +6,21 @@ module KeycloakAdmin
6
6
  @realm_client = realm_client
7
7
  end
8
8
 
9
+ def get(group_id)
10
+ response = execute_http do
11
+ RestClient::Resource.new(groups_url(group_id), @configuration.rest_client_options).get(headers)
12
+ end
13
+ GroupRepresentation.from_hash(JSON.parse(response))
14
+ end
15
+
16
+ def children(parent_id)
17
+ response = execute_http do
18
+ url = "#{groups_url(parent_id)}/children"
19
+ RestClient::Resource.new(url, @configuration.rest_client_options).get(headers)
20
+ end
21
+ JSON.parse(response).map { |group_as_hash| GroupRepresentation.from_hash(group_as_hash) }
22
+ end
23
+
9
24
  def list
10
25
  search(nil)
11
26
  end
@@ -25,29 +40,39 @@ module KeycloakAdmin
25
40
  JSON.parse(response).map { |group_as_hash| GroupRepresentation.from_hash(group_as_hash) }
26
41
  end
27
42
 
28
- def create!(name, path = nil)
29
- response = save(build(name, path))
43
+ def create!(name, path = nil, attributes = {})
44
+ response = save(build(name, path, attributes))
30
45
  created_id(response)
31
46
  end
32
47
 
33
48
  def save(group_representation)
34
49
  execute_http do
35
- RestClient::Resource.new(groups_url, @configuration.rest_client_options).post(
36
- create_payload(group_representation), headers
37
- )
50
+ payload = create_payload(group_representation)
51
+ if group_representation.id
52
+ RestClient::Resource.new(groups_url(group_representation.id), @configuration.rest_client_options).put(payload, headers)
53
+ else
54
+ RestClient::Resource.new(groups_url, @configuration.rest_client_options).post(payload, headers)
55
+ end
38
56
  end
39
57
  end
40
58
 
41
- def create_subgroup!(parent_id, name)
59
+ def create_subgroup!(parent_id, name, attributes = {})
42
60
  url = "#{groups_url(parent_id)}/children"
43
61
  response = execute_http do
44
62
  RestClient::Resource.new(url, @configuration.rest_client_options).post(
45
- create_payload(build(name, nil)), headers
63
+ create_payload(build(name, nil, attributes)), headers
46
64
  )
47
65
  end
48
66
  created_id(response)
49
67
  end
50
-
68
+
69
+ def delete(group_id)
70
+ execute_http do
71
+ RestClient::Resource.new(groups_url(group_id), @configuration.rest_client_options).delete(headers)
72
+ end
73
+ true
74
+ end
75
+
51
76
  def members(group_id, first=0, max=100)
52
77
  url = "#{groups_url(group_id)}/members"
53
78
  query = {first: first.try(:to_i), max: max.try(:to_i)}.compact
@@ -61,6 +86,28 @@ module KeycloakAdmin
61
86
  JSON.parse(response).map { |user_as_hash| UserRepresentation.from_hash(user_as_hash) }
62
87
  end
63
88
 
89
+ # Gets all realm-level roles for a group
90
+ def get_realm_level_roles(group_id)
91
+ url = "#{groups_url(group_id)}/role-mappings/realm"
92
+ response = execute_http do
93
+ RestClient::Resource.new(url, @configuration.rest_client_options).get(headers)
94
+ end
95
+ JSON.parse(response).map { |role_as_hash| RoleRepresentation.from_hash(role_as_hash) }
96
+ end
97
+
98
+ # Adds a realm-level role to a group via the role name
99
+ def add_realm_level_role_name!(group_id, role_name)
100
+ # creates a full role-representation object needed by the keycloak api to work
101
+ role_representation = RoleClient.new(@configuration, @realm_client).get(role_name)
102
+ url = "#{groups_url(group_id)}/role-mappings/realm"
103
+ response = execute_http do
104
+ RestClient::Resource.new(url, @configuration.rest_client_options).post(
105
+ create_payload([role_representation]), headers
106
+ )
107
+ end
108
+ role_representation
109
+ end
110
+
64
111
  def groups_url(id=nil)
65
112
  if id
66
113
  "#{@realm_client.realm_admin_url}/groups/#{id}"
@@ -71,11 +118,14 @@ module KeycloakAdmin
71
118
 
72
119
  private
73
120
 
74
- def build(name, path)
75
- group = GroupRepresentation.new
76
- group.name = name
77
- group.path = path
78
- group
121
+ def build(name, path, attributes)
122
+ GroupRepresentation.from_hash(
123
+ {
124
+ "name" => name,
125
+ "path" => path,
126
+ "attributes" => attributes
127
+ }
128
+ )
79
129
  end
80
130
  end
81
131
  end
@@ -13,32 +13,47 @@ module KeycloakAdmin
13
13
  JSON.parse(response).map { |role_as_hash| RoleRepresentation.from_hash(role_as_hash) }
14
14
  end
15
15
 
16
+ # Returns the role representation for the specified role name
16
17
  def get(name)
18
+ # allows special characters in the name like space
19
+ name = URI.encode_uri_component(name)
17
20
  response = execute_http do
18
21
  RestClient::Resource.new(role_name_url(name), @configuration.rest_client_options).get(headers)
19
22
  end
20
23
  RoleRepresentation.from_hash JSON.parse(response)
21
24
  end
22
25
 
26
+ # Lists all groups that have the specified role name assigned
27
+ def list_groups(name)
28
+ # allows special characters in the name like space
29
+ name = URI.encode_uri_component(name)
30
+ response = execute_http do
31
+ RestClient::Resource.new("#{role_name_url(name)}/groups", @configuration.rest_client_options).get(headers)
32
+ end
33
+ JSON.parse(response).map { |role_as_hash| GroupRepresentation.from_hash(role_as_hash) }
34
+ end
35
+
23
36
  def save(role_representation)
24
37
  execute_http do
25
- RestClient::Resource.new(roles_url, @configuration.rest_client_options).post(
26
- create_payload(role_representation), headers
27
- )
38
+ payload = create_payload(role_representation)
39
+ if role_representation.id
40
+ RestClient::Resource.new(role_id_url(role_representation.id), @configuration.rest_client_options).put(payload, headers)
41
+ else
42
+ RestClient::Resource.new(roles_url, @configuration.rest_client_options).post(payload, headers)
43
+ end
28
44
  end
29
45
  end
30
46
 
31
- def roles_url(id=nil)
32
- if id
33
- "#{@realm_client.realm_admin_url}/roles/#{id}"
34
- else
35
- "#{@realm_client.realm_admin_url}/roles"
36
- end
47
+ def roles_url
48
+ "#{@realm_client.realm_admin_url}/roles"
49
+ end
50
+
51
+ def role_id_url(id)
52
+ "#{@realm_client.realm_admin_url}/roles-by-id/#{id}"
37
53
  end
38
54
 
39
55
  def role_name_url(name)
40
56
  "#{@realm_client.realm_admin_url}/roles/#{name}"
41
57
  end
42
-
43
58
  end
44
59
  end
@@ -20,6 +20,7 @@ module KeycloakAdmin
20
20
  user_representation
21
21
  end
22
22
 
23
+ # pay attention that, since Keycloak 24.0.4, partial updates of attributes are not authorized anymore
23
24
  def update(user_id, user_representation_body)
24
25
  raise ArgumentError.new("user_id must be defined") if user_id.nil?
25
26
  RestClient::Request.execute(
@@ -3,14 +3,18 @@ module KeycloakAdmin
3
3
  attr_accessor :id,
4
4
  :name,
5
5
  :path,
6
+ :attributes,
7
+ :sub_group_count,
6
8
  :sub_groups
7
9
 
8
10
  def self.from_hash(hash)
9
- group = new
10
- group.id = hash["id"]
11
- group.name = hash["name"]
12
- group.path = hash["path"]
13
- group.sub_groups = hash.fetch("subGroups", []).map { |sub_group_hash| self.from_hash(sub_group_hash) }
11
+ group = new
12
+ group.id = hash["id"]
13
+ group.name = hash["name"]
14
+ group.path = hash["path"]
15
+ group.attributes = hash.fetch("attributes", {}).map { |k, v| [k.to_sym, Array(v)] }.to_h
16
+ group.sub_group_count = hash["subGroupCount"]
17
+ group.sub_groups = hash.fetch("subGroups", []).map { |sub_group_hash| self.from_hash(sub_group_hash) }
14
18
  group
15
19
  end
16
20
  end
@@ -3,7 +3,8 @@ module KeycloakAdmin
3
3
  attr_accessor :id,
4
4
  :name,
5
5
  :composite,
6
- :client_role
6
+ :client_role,
7
+ :container_id,
7
8
 
8
9
  def self.from_hash(hash)
9
10
  role = new
@@ -11,6 +12,7 @@ module KeycloakAdmin
11
12
  role.name = hash["name"]
12
13
  role.composite = hash["composite"]
13
14
  role.client_role = hash["clientRole"]
15
+ role.container_id = hash["containerId"]
14
16
  role
15
17
  end
16
18
  end
@@ -1,3 +1,3 @@
1
1
  module KeycloakAdmin
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.2"
3
3
  end
@@ -82,7 +82,7 @@ RSpec.describe KeycloakAdmin::ClientClient do
82
82
  end
83
83
 
84
84
  it "passes rest client options" do
85
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
85
+ rest_client_options = {timeout: 10}
86
86
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
87
87
 
88
88
  expect(RestClient::Resource).to receive(:new).with(
@@ -123,7 +123,7 @@ RSpec.describe KeycloakAdmin::ClientClient do
123
123
  end
124
124
 
125
125
  it "passes rest client options" do
126
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
126
+ rest_client_options = {timeout: 10}
127
127
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
128
128
  expect(RestClient::Resource).to receive(:new).with(
129
129
  "http://auth.service.io/auth/admin/realms/valid-realm/clients/95b45037-3980-404c-ba12-784fa1baf2c2", rest_client_options).and_call_original
@@ -32,7 +32,7 @@ RSpec.describe KeycloakAdmin::ClientRoleMappingsClient do
32
32
  end
33
33
 
34
34
  it "passes rest client options" do
35
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
35
+ rest_client_options = {timeout: 10}
36
36
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
37
37
 
38
38
  expect(RestClient::Resource).to receive(:new).with(
@@ -70,7 +70,7 @@ RSpec.describe KeycloakAdmin::ClientRoleMappingsClient do
70
70
  end
71
71
 
72
72
  it "passes rest client options" do
73
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
73
+ rest_client_options = {timeout: 10}
74
74
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
75
75
 
76
76
  expect(RestClient::Resource).to receive(:new).with(
@@ -22,6 +22,35 @@ RSpec.describe KeycloakAdmin::GroupClient do
22
22
  end
23
23
  end
24
24
 
25
+ describe "#get" do
26
+ let(:realm_name) { "valid-realm" }
27
+
28
+ before(:each) do
29
+ @group_client = KeycloakAdmin.realm(realm_name).groups
30
+
31
+ stub_token_client
32
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '{"id":"test_group_id","name":"test_group_name"}'
33
+ end
34
+
35
+ it "get a group" do
36
+ group = @group_client.get("test_group_id")
37
+ expect(group.id).to eq "test_group_id"
38
+ expect(group.name).to eq "test_group_name"
39
+ end
40
+
41
+ it "passes rest client options" do
42
+ rest_client_options = {timeout: 10}
43
+ allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
44
+
45
+ expect(RestClient::Resource).to receive(:new).with(
46
+ "http://auth.service.io/auth/admin/realms/valid-realm/groups/test_group_id", rest_client_options).and_call_original
47
+
48
+ group = @group_client.get("test_group_id")
49
+ expect(group.id).to eq "test_group_id"
50
+ expect(group.name).to eq "test_group_name"
51
+ end
52
+ end
53
+
25
54
  describe "#list" do
26
55
  let(:realm_name) { "valid-realm" }
27
56
 
@@ -39,7 +68,7 @@ RSpec.describe KeycloakAdmin::GroupClient do
39
68
  end
40
69
 
41
70
  it "passes rest client options" do
42
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
71
+ rest_client_options = {timeout: 10}
43
72
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
44
73
 
45
74
  expect(RestClient::Resource).to receive(:new).with(
@@ -51,35 +80,102 @@ RSpec.describe KeycloakAdmin::GroupClient do
51
80
  end
52
81
  end
53
82
 
54
- describe "#save" do
83
+
84
+ describe "#children" do
55
85
  let(:realm_name) { "valid-realm" }
56
- let(:group) { KeycloakAdmin::GroupRepresentation.from_hash(
57
- "name" => "test_group_name"
58
- )}
59
86
 
60
87
  before(:each) do
61
88
  @group_client = KeycloakAdmin.realm(realm_name).groups
62
89
 
63
90
  stub_token_client
64
- response = double
65
- allow(response).to receive(:headers).and_return(
66
- { location: 'http://auth.service.io/auth/admin/realms/valid-realm/groups/be061c48-6edd-4783-a726-1a57d4bfa22b' }
67
- )
68
- expect_any_instance_of(RestClient::Resource).to receive(:post).with(group.to_json, anything).and_return response
91
+ allow_any_instance_of(RestClient::Resource).to receive(:get).and_return '[{"id":"test_group_id","name":"test_group_name"}]'
69
92
  end
70
93
 
71
- it "saves a group" do
72
- @group_client.save(group)
94
+ it "lists children groups" do
95
+ groups = @group_client.children("parent_group_id")
96
+ expect(groups.length).to eq 1
97
+ expect(groups[0].name).to eq "test_group_name"
73
98
  end
74
99
 
75
100
  it "passes rest client options" do
76
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
101
+ rest_client_options = {timeout: 10}
77
102
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
78
103
 
79
104
  expect(RestClient::Resource).to receive(:new).with(
80
- "http://auth.service.io/auth/admin/realms/valid-realm/groups", rest_client_options).and_call_original
105
+ "http://auth.service.io/auth/admin/realms/valid-realm/groups/parent_group_id/children", rest_client_options).and_call_original
81
106
 
82
- @group_client.save(group)
107
+ groups = @group_client.children("parent_group_id")
108
+ expect(groups.length).to eq 1
109
+ expect(groups[0].name).to eq "test_group_name"
110
+ end
111
+ end
112
+
113
+ describe "#save" do
114
+ let(:realm_name) { "valid-realm" }
115
+
116
+ before(:each) do
117
+ @group_client = KeycloakAdmin.realm(realm_name).groups
118
+
119
+ stub_token_client
120
+ end
121
+
122
+ context "when the group does not exist" do
123
+ let(:group) { KeycloakAdmin::GroupRepresentation.from_hash(
124
+ "name" => "test_group_name"
125
+ )}
126
+
127
+ before do
128
+ response = double
129
+ allow(response).to receive(:headers).and_return(
130
+ { location: 'http://auth.service.io/auth/admin/realms/valid-realm/groups/be061c48-6edd-4783-a726-1a57d4bfa22b' }
131
+ )
132
+
133
+ expect_any_instance_of(RestClient::Resource).to receive(:post).with(group.to_json, anything).and_return response
134
+ end
135
+
136
+ it "saves a group" do
137
+ @group_client.save(group)
138
+ end
139
+
140
+ it "passes rest client options" do
141
+ rest_client_options = {timeout: 10}
142
+ allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
143
+
144
+ expect(RestClient::Resource).to receive(:new).with(
145
+ "http://auth.service.io/auth/admin/realms/valid-realm/groups", rest_client_options).and_call_original
146
+
147
+ @group_client.save(group)
148
+ end
149
+ end
150
+
151
+ context "when the group already exists" do
152
+ let(:group) { KeycloakAdmin::GroupRepresentation.from_hash(
153
+ "id" => "test_group_id",
154
+ "name" => "test_group_name"
155
+ )}
156
+
157
+ before do
158
+ response = double
159
+ allow(response).to receive(:headers).and_return(
160
+ { location: 'http://auth.service.io/auth/admin/realms/valid-realm/groups/be061c48-6edd-4783-a726-1a57d4bfa22b' }
161
+ )
162
+
163
+ expect_any_instance_of(RestClient::Resource).to receive(:put).with(group.to_json, anything).and_return response
164
+ end
165
+
166
+ it "saves a group" do
167
+ @group_client.save(group)
168
+ end
169
+
170
+ it "passes rest client options" do
171
+ rest_client_options = {timeout: 10}
172
+ allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
173
+
174
+ expect(RestClient::Resource).to receive(:new).with(
175
+ "http://auth.service.io/auth/admin/realms/valid-realm/groups/test_group_id", rest_client_options).and_call_original
176
+
177
+ @group_client.save(group)
178
+ end
83
179
  end
84
180
  end
85
181
 
@@ -133,4 +229,30 @@ RSpec.describe KeycloakAdmin::GroupClient do
133
229
  expect(group_id).to eq '7686af34-204c-4515-8122-78d19febbf6e'
134
230
  end
135
231
  end
232
+
233
+ describe "#delete" do
234
+ let(:realm_name) { "valid-realm" }
235
+
236
+ before(:each) do
237
+ @group_client = KeycloakAdmin.realm(realm_name).groups
238
+
239
+ stub_token_client
240
+ allow_any_instance_of(RestClient::Resource).to receive(:delete).and_return ''
241
+ end
242
+
243
+ it "deletes a group" do
244
+ result = @group_client.delete("test_group_id")
245
+ expect(result).to be(true)
246
+ end
247
+
248
+ it "raises a delete error" do
249
+ rest_client_options = {timeout: 10}
250
+ allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
251
+
252
+ expect(RestClient::Resource).to receive(:new).with(
253
+ "http://auth.service.io/auth/admin/realms/valid-realm/groups/test_group_id", rest_client_options).and_raise("error")
254
+
255
+ expect { @group_client.delete("test_group_id") }.to raise_error("error")
256
+ end
257
+ end
136
258
  end
@@ -78,7 +78,7 @@ RSpec.describe KeycloakAdmin::IdentityProviderClient do
78
78
  end
79
79
 
80
80
  it "passes rest client options" do
81
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
81
+ rest_client_options = {timeout: 10}
82
82
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
83
83
 
84
84
  expect(RestClient::Resource).to receive(:new).with(
@@ -60,7 +60,7 @@ RSpec.describe KeycloakAdmin::RealmClient do
60
60
  end
61
61
 
62
62
  it "passes rest client options" do
63
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
63
+ rest_client_options = {timeout: 10}
64
64
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
65
65
 
66
66
  expect(RestClient::Resource).to receive(:new).with(
@@ -87,7 +87,7 @@ RSpec.describe KeycloakAdmin::RealmClient do
87
87
  end
88
88
 
89
89
  it "passes rest client options" do
90
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
90
+ rest_client_options = {timeout: 10}
91
91
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
92
92
 
93
93
  expect(RestClient::Resource).to receive(:new).with(
@@ -117,7 +117,7 @@ RSpec.describe KeycloakAdmin::RealmClient do
117
117
  end
118
118
 
119
119
  it "passes rest client options" do
120
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
120
+ rest_client_options = {timeout: 10}
121
121
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
122
122
 
123
123
  expect(RestClient::Resource).to receive(:new).with(
@@ -143,7 +143,7 @@ RSpec.describe KeycloakAdmin::RealmClient do
143
143
  end
144
144
 
145
145
  it "passes rest client options" do
146
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
146
+ rest_client_options = {timeout: 10}
147
147
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
148
148
 
149
149
  expect(RestClient::Resource).to receive(:new).with(
@@ -1,24 +1,20 @@
1
1
  RSpec.describe KeycloakAdmin::RoleClient do
2
2
  describe "#roles_url" do
3
3
  let(:realm_name) { "valid-realm" }
4
- let(:role_id) { nil }
5
4
 
6
- before(:each) do
7
- @built_url = KeycloakAdmin.realm(realm_name).roles.roles_url(role_id)
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
8
  end
9
+ end
9
10
 
10
- context "when role_id is not defined" do
11
- let(:role_id) { nil }
12
- it "return a proper url without role id" do
13
- expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/valid-realm/roles"
14
- end
15
- end
11
+ describe "#role_id_url" do
12
+ let(:realm_name) { "valid-realm" }
13
+ let(:role_id) { "95985b21-d884-4bbd-b852-cb8cd365afc2" }
16
14
 
17
- context "when role_id is defined" do
18
- let(:role_id) { "95985b21-d884-4bbd-b852-cb8cd365afc2" }
19
- it "return a proper url with the role id" do
20
- expect(@built_url).to eq "http://auth.service.io/auth/admin/realms/valid-realm/roles/95985b21-d884-4bbd-b852-cb8cd365afc2"
21
- end
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"
22
18
  end
23
19
  end
24
20
 
@@ -39,7 +35,7 @@ RSpec.describe KeycloakAdmin::RoleClient do
39
35
  end
40
36
 
41
37
  it "passes rest client options" do
42
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
38
+ rest_client_options = {timeout: 10}
43
39
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
44
40
 
45
41
  expect(RestClient::Resource).to receive(:new).with(
@@ -71,7 +67,7 @@ RSpec.describe KeycloakAdmin::RoleClient do
71
67
  end
72
68
 
73
69
  it "passes rest client options" do
74
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
70
+ rest_client_options = {timeout: 10}
75
71
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
76
72
 
77
73
  expect(RestClient::Resource).to receive(:new).with(
@@ -56,7 +56,7 @@ RSpec.describe KeycloakAdmin::RoleMapperClient do
56
56
  end
57
57
 
58
58
  it "passes rest client options" do
59
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
59
+ rest_client_options = {timeout: 10}
60
60
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
61
61
 
62
62
  expect(RestClient::Resource).to receive(:new).with(
@@ -49,7 +49,7 @@ RSpec.describe KeycloakAdmin::TokenClient do
49
49
  end
50
50
 
51
51
  it "passes rest client options" do
52
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
52
+ rest_client_options = {timeout: 10}
53
53
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
54
54
  stub_post
55
55
 
@@ -141,7 +141,7 @@ RSpec.describe KeycloakAdmin::TokenClient do
141
141
  end
142
142
 
143
143
  it "passes rest client options" do
144
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
144
+ rest_client_options = {timeout: 10}
145
145
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
146
146
 
147
147
  expect(RestClient::Resource).to receive(:new).with(
@@ -167,7 +167,7 @@ RSpec.describe KeycloakAdmin::TokenClient do
167
167
  end
168
168
 
169
169
  it "passes rest client options" do
170
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
170
+ rest_client_options = {timeout: 10}
171
171
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
172
172
 
173
173
  expect(RestClient::Resource).to receive(:new).with(
@@ -213,7 +213,7 @@ RSpec.describe KeycloakAdmin::TokenClient do
213
213
  end
214
214
 
215
215
  it "passes rest client options" do
216
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
216
+ rest_client_options = {timeout: 10}
217
217
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
218
218
 
219
219
  expect(RestClient::Resource).to receive(:new).with(
@@ -246,7 +246,7 @@ RSpec.describe KeycloakAdmin::TokenClient do
246
246
  end
247
247
 
248
248
  it "passes rest client options" do
249
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
249
+ rest_client_options = {timeout: 10}
250
250
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
251
251
 
252
252
  expect(RestClient::Resource).to receive(:new).with(
@@ -273,7 +273,7 @@ RSpec.describe KeycloakAdmin::TokenClient do
273
273
  end
274
274
 
275
275
  it "passes rest client options" do
276
- rest_client_options = {verify_ssl: OpenSSL::SSL::VERIFY_NONE}
276
+ rest_client_options = {timeout: 10}
277
277
  allow_any_instance_of(KeycloakAdmin::Configuration).to receive(:rest_client_options).and_return rest_client_options
278
278
 
279
279
  expect(RestClient::Resource).to receive(:new).with(
@@ -6,7 +6,7 @@ RSpec.describe KeycloakAdmin::RealmClient do
6
6
  let(:use_service_account) { true }
7
7
  let(:username) { "a" }
8
8
  let(:password) { "b" }
9
- let(:rest_client_options) { {verify_ssl: OpenSSL::SSL::VERIFY_NONE} }
9
+ let(:rest_client_options) { {timeout: 10 } }
10
10
 
11
11
  before(:each) do
12
12
  @configuration = KeycloakAdmin::Configuration.new
@@ -4,10 +4,17 @@ RSpec.describe KeycloakAdmin::GroupRepresentation do
4
4
  it "parses the sub groups into group representations" do
5
5
  group = described_class.from_hash({
6
6
  "name" => "group a",
7
+ "attributes" => {
8
+ "key" => ["value"]
9
+ },
10
+ "subGroupCount" => 1,
7
11
  "subGroups" => [{
8
12
  "name" => "subgroup b"
9
13
  }]
10
14
  })
15
+
16
+ expect(group.attributes).to eq(key: ["value"])
17
+ expect(group.sub_group_count).to eq 1
11
18
  expect(group.sub_groups.length).to eq 1
12
19
  expect(group.sub_groups.first).to be_a described_class
13
20
  end
@@ -12,7 +12,7 @@ RSpec.describe KeycloakAdmin::RoleRepresentation do
12
12
  end
13
13
 
14
14
  it "can convert to json" do
15
- expect(@mapper.to_json).to eq "{\"id\":\"bb79fb10-a7b4-4728-a662-82a4de7844a3\",\"name\":\"abcd\",\"composite\":true,\"clientRole\":false}"
15
+ expect(@mapper.to_json).to eq "{\"id\":\"bb79fb10-a7b4-4728-a662-82a4de7844a3\",\"name\":\"abcd\",\"composite\":true,\"clientRole\":false,\"containerId\":null}"
16
16
  end
17
17
  end
18
18
 
@@ -31,7 +31,7 @@ RSpec.describe KeycloakAdmin::RoleRepresentation do
31
31
  end
32
32
 
33
33
  it "can convert to json" do
34
- expect(@mappers.to_json).to eq "[{\"id\":\"bb79fb10-a7b4-4728-a662-82a4de7844a3\",\"name\":\"abcd\",\"composite\":true,\"clientRole\":false}]"
34
+ expect(@mappers.to_json).to eq "[{\"id\":\"bb79fb10-a7b4-4728-a662-82a4de7844a3\",\"name\":\"abcd\",\"composite\":true,\"clientRole\":false,\"containerId\":null}]"
35
35
  end
36
36
  end
37
37
  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: 1.1.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorent Lempereur
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-03 00:00:00.000000000 Z
11
+ date: 2024-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-cookie