5
5
6
6
import java .util .ArrayList ;
7
7
import java .util .HashMap ;
8
+ import java .util .HashSet ;
8
9
import java .util .List ;
9
10
import java .util .Map ;
11
+ import java .util .Optional ;
10
12
import java .util .Set ;
13
+ import java .util .stream .Stream ;
11
14
12
15
import jakarta .enterprise .context .ApplicationScoped ;
13
16
import jakarta .inject .Inject ;
@@ -76,8 +79,32 @@ public List<UserService.UserData> searchUsers(String query) {
76
79
77
80
@ Override
78
81
public List <String > getRoles (String username ) {
79
- return keycloak .realm (realm ).users ().get (findMatchingUser (username ).getId ()).roles ().realmLevel ().listAll ().stream ()
80
- .map (RoleRepresentation ::getName ).toList ();
82
+ List <RoleRepresentation > representations = keycloak .realm (realm ).users ().get (findMatchingUserId (username )).roles ()
83
+ .realmLevel ().listAll ();
84
+
85
+ // the realm level roles does not include the base roles, only the composites, so add them manually
86
+ Set <String > roles = new HashSet <>(representations .stream ().map (RoleRepresentation ::getName ).toList ());
87
+ for (String r : List .of (Roles .MANAGER , Roles .TESTER , Roles .UPLOADER , Roles .VIEWER )) {
88
+ Optional <String > composite = roles .stream ().filter (role -> role .endsWith (r )).findAny ();
89
+ if (composite .isPresent ()) {
90
+ roles .add (r );
91
+ roles .add (composite .get ().substring (0 , composite .get ().length () - r .length () - 1 ) + "-team" );
92
+ }
93
+ }
94
+ return new ArrayList <>(roles );
95
+
96
+ // the right way to do this would be something like this (avoided because it does call keycloak a bunch of times)
97
+ // return representations.stream().flatMap(this::getRoleAndComposites).toList();
98
+ }
99
+
100
+ private Stream <String > getRoleAndComposites (RoleRepresentation representation ) {
101
+ Set <String > roles = new HashSet <>();
102
+ if (representation .isComposite ()) {
103
+ keycloak .realm (realm ).rolesById ().getRealmRoleComposites (representation .getId ()).stream ()
104
+ .flatMap (this ::getRoleAndComposites ).forEach (roles ::add );
105
+ }
106
+ roles .add (representation .getName ());
107
+ return roles .stream ();
81
108
}
82
109
83
110
@ Override
@@ -119,7 +146,7 @@ public void createUser(UserService.NewUser user) {
119
146
120
147
try { // assign the provided roles to the realm
121
148
UsersResource usersResource = keycloak .realm (realm ).users ();
122
- String userId = findMatchingUser (rep .getUsername ()). getId ( );
149
+ String userId = findMatchingUserId (rep .getUsername ());
123
150
124
151
if (user .team != null ) {
125
152
String prefix = getTeamPrefix (user .team );
@@ -148,7 +175,7 @@ public void createUser(UserService.NewUser user) {
148
175
149
176
@ Override
150
177
public void removeUser (String username ) {
151
- try (Response response = keycloak .realm (realm ).users ().delete (findMatchingUser (username ). getId ( ))) {
178
+ try (Response response = keycloak .realm (realm ).users ().delete (findMatchingUserId (username ))) {
152
179
if (response .getStatusInfo ().getFamily () != Response .Status .Family .SUCCESSFUL ) {
153
180
LOG .warnv ("Got {0} response for removing user {0}" , response .getStatusInfo (), username );
154
181
throw ServiceException .serverError (format ("Unable to remove user {0}" , username ));
@@ -187,7 +214,7 @@ public List<String> getTeams() { // get the "team roles" in the realm
187
214
}
188
215
}
189
216
190
- private UserRepresentation findMatchingUser (String username ) { // find the clientID of a single user
217
+ private String findMatchingUserId (String username ) { // find the clientID of a single user
191
218
List <UserRepresentation > matchingUsers = keycloak .realm (realm ).users ().search (username , true );
192
219
if (matchingUsers == null || matchingUsers .isEmpty ()) {
193
220
LOG .warnv ("Cannot find user with username {0}" , username );
@@ -197,7 +224,7 @@ private UserRepresentation findMatchingUser(String username) { // find the clien
197
224
matchingUsers .stream ().map (UserRepresentation ::getId ).collect (joining (" " )));
198
225
throw ServiceException .serverError (format ("More than one user with username {0}" , username ));
199
226
}
200
- return matchingUsers .get (0 );
227
+ return matchingUsers .get (0 ). getId () ;
201
228
}
202
229
203
230
@ Override
@@ -227,10 +254,9 @@ public void updateTeamMembers(String team, Map<String, List<String>> roles) { //
227
254
RoleMappingResource rolesMappingResource ;
228
255
229
256
try { // fetch the current roles for the user
230
- String userId = findMatchingUser (entry .getKey ()). getId ( );
257
+ String userId = findMatchingUserId (entry .getKey ());
231
258
rolesMappingResource = keycloak .realm (realm ).users ().get (userId ).roles ();
232
- existingRoles = rolesMappingResource .getAll ().getRealmMappings ().stream ().map (RoleRepresentation ::getName )
233
- .toList ();
259
+ existingRoles = rolesMappingResource .realmLevel ().listAll ().stream ().map (RoleRepresentation ::getName ).toList ();
234
260
} catch (Throwable t ) {
235
261
LOG .warnv (t , "Failed to retrieve current roles of user {0} from Keycloak" , entry .getKey ());
236
262
throw ServiceException
@@ -267,6 +293,8 @@ public void updateTeamMembers(String team, Map<String, List<String>> roles) { //
267
293
}
268
294
}
269
295
}
296
+ } catch (NotFoundException e ) {
297
+ throw ServiceException .serverError (format ("The team {0} does not exist" , team ));
270
298
} catch (Throwable t ) {
271
299
LOG .warnv (t , "Failed to remove all roles of team {0}" , team );
272
300
throw ServiceException .serverError (format ("Failed to remove all roles of team {0}" , team ));
@@ -376,7 +404,7 @@ public void updateAdministrators(List<String> newAdmins) { // update the list of
376
404
for (String username : newAdmins ) { // add admin role for `newAdmins` not in `oldAdmins`
377
405
if (oldAdmins .stream ().noneMatch (old -> username .equals (old .getUsername ()))) {
378
406
try {
379
- usersResource .get (findMatchingUser (username ). getId ( )).roles ().realmLevel ().add (List .of (adminRole ));
407
+ usersResource .get (findMatchingUserId (username )).roles ().realmLevel ().add (List .of (adminRole ));
380
408
LOG .infov ("Added administrator role to user {0}" , username );
381
409
} catch (Throwable t ) {
382
410
LOG .warnv ("Could not add admin role to user {0} due to {1}" , username , t .getMessage ());
@@ -398,7 +426,7 @@ public void setPassword(String username, String password) {
398
426
credentials .setType (CredentialRepresentation .PASSWORD );
399
427
credentials .setValue (password );
400
428
401
- keycloak .realm (realm ).users ().get (findMatchingUser (username ). getId ( )).resetPassword (credentials );
429
+ keycloak .realm (realm ).users ().get (findMatchingUserId (username )).resetPassword (credentials );
402
430
} catch (Throwable t ) {
403
431
LOG .warnv (t , "Failed to retrieve current representation of user {0} from Keycloak" , username );
404
432
throw ServiceException
0 commit comments