Skip to content

Commit 1446ef2

Browse files
authored
Merge pull request #54 from garry08/add-user-join-leave-group
Add user join/leave group endpoint in Users
2 parents f691e00 + 5a0969c commit 1446ef2

File tree

4 files changed

+168
-0
lines changed

4 files changed

+168
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ More examples can be found in the [examples](examples) directory.
9696
| `PUT /admin/realms/{realm}/users/{userId}` | `n/a` | [Users::update()](src/Resource/Users.php) |
9797
| `DELETE /admin/realms/{realm}/users/{userId}` | `n/a` | [Users::delete()](src/Resource/Users.php) |
9898
| `GET /admin/realms/{realm}/users` | [UserCollection](src/Collection/UserCollection.php) | [Users::search()](src/Resource/Users.php) |
99+
| `PUT /{realm}/users/{id}/groups/{groupId}` | `n/a` | [Users::joinGroup()](src/Resource/Users.php) |
100+
| `DELETE /{realm}/users/{id}/groups/{groupId}` | `n/a` | [Users::leaveGroup()](src/Resource/Users.php) |
101+
| `GET /{realm}/users/{id}/groups` | [GroupCollection](src/Collection/GroupCollection.php) | [Users::retrieveGroups()](src/Resource/Users.php) |
99102

100103
### [Root](https://www.keycloak.org/docs-api/20.0.0/rest-api/index.html#_root_resource)
101104
| Endpoint | Response | API |

src/Resource/Users.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Fschmtt\Keycloak\Resource;
66

7+
use Fschmtt\Keycloak\Collection\GroupCollection;
78
use Fschmtt\Keycloak\Collection\UserCollection;
89
use Fschmtt\Keycloak\Http\Command;
910
use Fschmtt\Keycloak\Http\Criteria;
@@ -97,4 +98,49 @@ public function search(string $realm, ?Criteria $criteria = null): UserCollectio
9798
)
9899
);
99100
}
101+
102+
public function joinGroup(string $realm, string $userId, string $groupId): void
103+
{
104+
$this->commandExecutor->executeCommand(
105+
new Command(
106+
'/admin/realms/{realm}/users/{userId}/groups/{groupId}',
107+
Method::PUT,
108+
[
109+
'realm' => $realm,
110+
'userId' => $userId,
111+
'groupId' => $groupId,
112+
]
113+
)
114+
);
115+
}
116+
117+
public function leaveGroup(string $realm, string $userId, string $groupId): void
118+
{
119+
$this->commandExecutor->executeCommand(
120+
new Command(
121+
'/admin/realms/{realm}/users/{userId}/groups/{groupId}',
122+
Method::DELETE,
123+
[
124+
'realm' => $realm,
125+
'userId' => $userId,
126+
'groupId' => $groupId,
127+
]
128+
)
129+
);
130+
}
131+
132+
public function retrieveGroups(string $realm, string $userId, ?Criteria $criteria = null): GroupCollection
133+
{
134+
return $this->queryExecutor->executeQuery(
135+
new Query(
136+
'/admin/realms/{realm}/users/{userId}/groups',
137+
GroupCollection::class,
138+
[
139+
'realm' => $realm,
140+
'userId' => $userId,
141+
],
142+
$criteria
143+
)
144+
);
145+
}
100146
}

tests/Integration/Resource/UsersTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Exception;
88
use Fschmtt\Keycloak\Http\Criteria;
9+
use Fschmtt\Keycloak\Representation\Group;
910
use Fschmtt\Keycloak\Representation\User;
1011
use Fschmtt\Keycloak\Test\Integration\IntegrationTestBehaviour;
1112
use PHPUnit\Framework\TestCase;
@@ -66,4 +67,37 @@ public function testImportSearchUpdateDeleteUser(): void
6667
static::assertSame(404, $e->getCode());
6768
}
6869
}
70+
71+
public function testJoinRetrieveLeaveGroupUser(): void
72+
{
73+
$users = $this->getKeycloak()->users();
74+
$user = $users->all('master')->first();
75+
76+
// create a temp group required for our test
77+
$groups = $this->getKeycloak()->groups();
78+
$groupName = Uuid::uuid4()->toString();
79+
$groups->create(
80+
'master',
81+
new Group(name: $groupName),
82+
);
83+
$group = $groups->all('master')->first();
84+
85+
// join group
86+
$users->joinGroup('master', $user->getId(), $group->getId());
87+
88+
$userGroups = $users->retrieveGroups('master', $user->getId());
89+
static::assertGreaterThanOrEqual(1, $userGroups->count());
90+
$userFirstGroup = $userGroups->first();
91+
static::assertInstanceOf(Group::class, $userFirstGroup);
92+
static::assertSame($group->getId(), $userFirstGroup->getId());
93+
94+
// leave group
95+
$users->leaveGroup('master', $user->getId(), $group->getId());
96+
97+
$userGroups = $users->retrieveGroups('master', $user->getId());
98+
static::assertGreaterThanOrEqual(0, $userGroups->count());
99+
100+
// remove the temp group
101+
$groups->delete('master', $group->getId());
102+
}
69103
}

tests/Unit/Resource/UsersTest.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
namespace Fschmtt\Keycloak\Test\Unit\Resource;
66

7+
use Fschmtt\Keycloak\Collection\GroupCollection;
78
use Fschmtt\Keycloak\Collection\UserCollection;
89
use Fschmtt\Keycloak\Http\Command;
910
use Fschmtt\Keycloak\Http\CommandExecutor;
1011
use Fschmtt\Keycloak\Http\Criteria;
1112
use Fschmtt\Keycloak\Http\Method;
1213
use Fschmtt\Keycloak\Http\Query;
1314
use Fschmtt\Keycloak\Http\QueryExecutor;
15+
use Fschmtt\Keycloak\Representation\Group;
1416
use Fschmtt\Keycloak\Representation\User;
1517
use Fschmtt\Keycloak\Resource\Users;
1618
use PHPUnit\Framework\TestCase;
@@ -190,4 +192,87 @@ public function testSearchUser(): void
190192

191193
$users->search('test-realm', $criteria);
192194
}
195+
196+
public function testJoinGroup(): void
197+
{
198+
$command = new Command(
199+
'/admin/realms/{realm}/users/{userId}/groups/{groupId}',
200+
Method::PUT,
201+
[
202+
'realm' => 'test-realm',
203+
'userId' => 'test-user',
204+
'groupId' => 'test-group',
205+
],
206+
);
207+
208+
$commandExecutor = $this->createMock(CommandExecutor::class);
209+
$commandExecutor->expects(static::once())
210+
->method('executeCommand')
211+
->with($command);
212+
213+
$users = new Users(
214+
$commandExecutor,
215+
$this->createMock(QueryExecutor::class),
216+
);
217+
218+
$users->joinGroup('test-realm', 'test-user', 'test-group');
219+
}
220+
221+
public function testLeaveGroup(): void
222+
{
223+
$command = new Command(
224+
'/admin/realms/{realm}/users/{userId}/groups/{groupId}',
225+
Method::DELETE,
226+
[
227+
'realm' => 'test-realm',
228+
'userId' => 'test-user',
229+
'groupId' => 'test-group',
230+
],
231+
);
232+
233+
$commandExecutor = $this->createMock(CommandExecutor::class);
234+
$commandExecutor->expects(static::once())
235+
->method('executeCommand')
236+
->with($command);
237+
238+
$users = new Users(
239+
$commandExecutor,
240+
$this->createMock(QueryExecutor::class),
241+
);
242+
243+
$users->leaveGroup('test-realm', 'test-user', 'test-group');
244+
}
245+
246+
public function testRetrieveGroups(): void
247+
{
248+
$query = new Query(
249+
'/admin/realms/{realm}/users/{userId}/groups',
250+
GroupCollection::class,
251+
[
252+
'realm' => 'test-realm',
253+
'userId' => 'test-user',
254+
],
255+
);
256+
257+
$groupCollection = new GroupCollection([
258+
new Group(id: 'test-group-1'),
259+
new Group(id: 'test-group-2'),
260+
]);
261+
262+
$queryExecutor = $this->createMock(QueryExecutor::class);
263+
$queryExecutor->expects(static::once())
264+
->method('executeQuery')
265+
->with($query)
266+
->willReturn($groupCollection);
267+
268+
$users = new Users(
269+
$this->createMock(CommandExecutor::class),
270+
$queryExecutor,
271+
);
272+
273+
static::assertSame(
274+
$groupCollection,
275+
$users->retrieveGroups('test-realm', 'test-user')
276+
);
277+
}
193278
}

0 commit comments

Comments
 (0)