Add briefRepresentation query parameter to getUsersInRole endpoint
Closes #29480 Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
parent
6b135ff6e7
commit
592c2250fc
8 changed files with 60 additions and 22 deletions
|
@ -120,9 +120,8 @@ public interface RoleResource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get role members.
|
* Get role members.
|
||||||
* <p/>
|
* <p>Returns users that have the given role, sorted by username ascending, paginated according to the query
|
||||||
* Returns users that have the given role, sorted by username ascending, paginated according to the query
|
* parameters.</p>
|
||||||
* parameters.
|
|
||||||
*
|
*
|
||||||
* @param firstResult Pagination offset
|
* @param firstResult Pagination offset
|
||||||
* @param maxResults Pagination size
|
* @param maxResults Pagination size
|
||||||
|
@ -133,11 +132,27 @@ public interface RoleResource {
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
List<UserRepresentation> getUserMembers(@QueryParam("first") Integer firstResult,
|
List<UserRepresentation> getUserMembers(@QueryParam("first") Integer firstResult,
|
||||||
@QueryParam("max") Integer maxResults);
|
@QueryParam("max") Integer maxResults);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get role members.
|
||||||
|
* <p>Returns users that have the given role, sorted by username ascending, paginated according to the query
|
||||||
|
* parameters.</p>
|
||||||
|
*
|
||||||
|
* @param briefRepresentation If the user should be returned in brief or full representation
|
||||||
|
* @param firstResult Pagination offset
|
||||||
|
* @param maxResults Pagination size
|
||||||
|
* @return a list of users with the given role
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("users")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
List<UserRepresentation> getUserMembers(@QueryParam("briefRepresentation") Boolean briefRepresentation,
|
||||||
|
@QueryParam("first") Integer firstResult,
|
||||||
|
@QueryParam("max") Integer maxResults);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get role groups
|
* Get role groups.
|
||||||
* <p/>
|
* <p>Returns groups that have the given role.</p>
|
||||||
* Returns groups that have the given role
|
|
||||||
*
|
*
|
||||||
* @return a list of groups with the given role
|
* @return a list of groups with the given role
|
||||||
*/
|
*/
|
||||||
|
@ -147,9 +162,8 @@ public interface RoleResource {
|
||||||
Set<GroupRepresentation> getRoleGroupMembers();
|
Set<GroupRepresentation> getRoleGroupMembers();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get role groups
|
* Get role groups.
|
||||||
* <p/>
|
* <p>Returns groups that have the given role, paginated according to the query parameters.</p>
|
||||||
* Returns groups that have the given role, paginated according to the query parameters
|
|
||||||
*
|
*
|
||||||
* @param firstResult Pagination offset
|
* @param firstResult Pagination offset
|
||||||
* @param maxResults Pagination size
|
* @param maxResults Pagination size
|
||||||
|
@ -162,9 +176,8 @@ public interface RoleResource {
|
||||||
@QueryParam("max") Integer maxResults);
|
@QueryParam("max") Integer maxResults);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get role members
|
* Get role members.
|
||||||
* <p/>
|
* <p>Returns users that have the given role.</p>
|
||||||
* Returns users that have the given role
|
|
||||||
*
|
*
|
||||||
* @return a set of users with the given role
|
* @return a set of users with the given role
|
||||||
*
|
*
|
||||||
|
@ -177,9 +190,8 @@ public interface RoleResource {
|
||||||
Set<UserRepresentation> getRoleUserMembers();
|
Set<UserRepresentation> getRoleUserMembers();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get role members
|
* Get role members.
|
||||||
* <p/>
|
* <p>Returns users that have the given role, paginated according to the query parameters.</p>
|
||||||
* Returns users that have the given role, paginated according to the query parameters
|
|
||||||
*
|
*
|
||||||
* @param firstResult Pagination offset
|
* @param firstResult Pagination offset
|
||||||
* @param maxResults Pagination size
|
* @param maxResults Pagination size
|
||||||
|
|
|
@ -30,6 +30,7 @@ export const UsersInRoleTab = () => {
|
||||||
return adminClient.clients.findUsersWithRole({
|
return adminClient.clients.findUsersWithRole({
|
||||||
roleName: role.name!,
|
roleName: role.name!,
|
||||||
id: clientId,
|
id: clientId,
|
||||||
|
briefRepresentation: true,
|
||||||
first,
|
first,
|
||||||
max,
|
max,
|
||||||
});
|
});
|
||||||
|
@ -37,6 +38,7 @@ export const UsersInRoleTab = () => {
|
||||||
|
|
||||||
return adminClient.roles.findUsersWithRole({
|
return adminClient.roles.findUsersWithRole({
|
||||||
name: role.name!,
|
name: role.name!,
|
||||||
|
briefRepresentation: true,
|
||||||
first,
|
first,
|
||||||
max,
|
max,
|
||||||
});
|
});
|
||||||
|
|
|
@ -139,7 +139,13 @@ export class Clients extends Resource<{ realm?: string }> {
|
||||||
});
|
});
|
||||||
|
|
||||||
public findUsersWithRole = this.makeRequest<
|
public findUsersWithRole = this.makeRequest<
|
||||||
{ id: string; roleName: string; first?: number; max?: number },
|
{
|
||||||
|
id: string;
|
||||||
|
roleName: string;
|
||||||
|
briefRepresentation?: boolean;
|
||||||
|
first?: number;
|
||||||
|
max?: number;
|
||||||
|
},
|
||||||
UserRepresentation[]
|
UserRepresentation[]
|
||||||
>({
|
>({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
@ -58,7 +58,12 @@ export class Roles extends Resource<{ realm?: string }> {
|
||||||
});
|
});
|
||||||
|
|
||||||
public findUsersWithRole = this.makeRequest<
|
public findUsersWithRole = this.makeRequest<
|
||||||
{ name: string; first?: number; max?: number },
|
{
|
||||||
|
name: string;
|
||||||
|
briefRepresentation?: boolean;
|
||||||
|
first?: number;
|
||||||
|
max?: number;
|
||||||
|
},
|
||||||
UserRepresentation[]
|
UserRepresentation[]
|
||||||
>({
|
>({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
@ -733,7 +733,10 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("usersInRole", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("usersInRole", UserEntity.class);
|
||||||
query.setParameter("roleId", role.getId());
|
query.setParameter("roleId", role.getId());
|
||||||
|
|
||||||
return closing(paginateQuery(query, firstResult, maxResults).getResultStream().map(user -> new UserAdapter(session, realm, em, user)));
|
final UserProvider users = session.users();
|
||||||
|
return closing(paginateQuery(query, firstResult, maxResults).getResultStream())
|
||||||
|
.map(userEntity -> users.getUserById(realm, userEntity.getId()))
|
||||||
|
.filter(Objects::nonNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.keycloak.models.ModelDuplicateException;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleContainerModel;
|
import org.keycloak.models.RoleContainerModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.ModelToRepresentation;
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.representations.idm.GroupRepresentation;
|
import org.keycloak.representations.idm.GroupRepresentation;
|
||||||
import org.keycloak.representations.idm.ManagementPermissionReference;
|
import org.keycloak.representations.idm.ManagementPermissionReference;
|
||||||
|
@ -477,6 +478,7 @@ public class RoleContainerResource extends RoleResource {
|
||||||
* @param roleName the role name.
|
* @param roleName the role name.
|
||||||
* @param firstResult first result to return. Ignored if negative or {@code null}.
|
* @param firstResult first result to return. Ignored if negative or {@code null}.
|
||||||
* @param maxResults maximum number of results to return. Ignored if negative or {@code null}.
|
* @param maxResults maximum number of results to return. Ignored if negative or {@code null}.
|
||||||
|
* @param briefRepresentation Boolean which defines whether brief representations are returned (default: false)
|
||||||
* @return a non-empty {@code Stream} of users.
|
* @return a non-empty {@code Stream} of users.
|
||||||
*/
|
*/
|
||||||
@Path("{role-name}/users")
|
@Path("{role-name}/users")
|
||||||
|
@ -486,6 +488,7 @@ public class RoleContainerResource extends RoleResource {
|
||||||
@Tag(name = KeycloakOpenAPI.Admin.Tags.ROLES)
|
@Tag(name = KeycloakOpenAPI.Admin.Tags.ROLES)
|
||||||
@Operation( summary = "Returns a stream of users that have the specified role name.")
|
@Operation( summary = "Returns a stream of users that have the specified role name.")
|
||||||
public Stream<UserRepresentation> getUsersInRole(final @Parameter(description = "the role name.") @PathParam("role-name") String roleName,
|
public Stream<UserRepresentation> getUsersInRole(final @Parameter(description = "the role name.") @PathParam("role-name") String roleName,
|
||||||
|
@Parameter(description = "Boolean which defines whether brief representations are returned (default: false)") @QueryParam("briefRepresentation") Boolean briefRepresentation,
|
||||||
@Parameter(description = "first result to return. Ignored if negative or {@code null}.") @QueryParam("first") Integer firstResult,
|
@Parameter(description = "first result to return. Ignored if negative or {@code null}.") @QueryParam("first") Integer firstResult,
|
||||||
@Parameter(description = "maximum number of results to return. Ignored if negative or {@code null}.") @QueryParam("max") Integer maxResults) {
|
@Parameter(description = "maximum number of results to return. Ignored if negative or {@code null}.") @QueryParam("max") Integer maxResults) {
|
||||||
|
|
||||||
|
@ -498,8 +501,11 @@ public class RoleContainerResource extends RoleResource {
|
||||||
throw new NotFoundException("Could not find role");
|
throw new NotFoundException("Could not find role");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Function<UserModel, UserRepresentation> toRepresentation = briefRepresentation != null && briefRepresentation
|
||||||
|
? ModelToRepresentation::toBriefRepresentation
|
||||||
|
: user -> ModelToRepresentation.toRepresentation(session, realm, user);
|
||||||
return session.users().getRoleMembersStream(realm, role, firstResult, maxResults)
|
return session.users().getRoleMembersStream(realm, role, firstResult, maxResults)
|
||||||
.map(user -> ModelToRepresentation.toRepresentation(session, realm, user));
|
.map(toRepresentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -239,8 +239,10 @@ public class ClientRolesTest extends AbstractClientTest {
|
||||||
// pagination
|
// pagination
|
||||||
List<UserRepresentation> usersInRole1 = roleResource.getUserMembers(0, 5);
|
List<UserRepresentation> usersInRole1 = roleResource.getUserMembers(0, 5);
|
||||||
assertEquals(createUsernames(0, 5), extractUsernames(usersInRole1));
|
assertEquals(createUsernames(0, 5), extractUsernames(usersInRole1));
|
||||||
List<UserRepresentation> usersInRole2 = roleResource.getUserMembers(5, 10);
|
Assert.assertNotNull("Not in full representation", usersInRole1.get(0).getNotBefore());
|
||||||
|
List<UserRepresentation> usersInRole2 = roleResource.getUserMembers(true, 5, 10);
|
||||||
assertEquals(createUsernames(5, 10), extractUsernames(usersInRole2));
|
assertEquals(createUsernames(5, 10), extractUsernames(usersInRole2));
|
||||||
|
Assert.assertNull("Not in brief representation", usersInRole2.get(0).getNotBefore());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> createUsernames(int startIndex, int endIndex) {
|
private static List<String> createUsernames(int startIndex, int endIndex) {
|
||||||
|
|
|
@ -352,12 +352,14 @@ public class RealmRolesTest extends AbstractAdminTest {
|
||||||
|
|
||||||
List<UserRepresentation> roleUserMembers = roleResource.getUserMembers(0, 1);
|
List<UserRepresentation> roleUserMembers = roleResource.getUserMembers(0, 1);
|
||||||
assertEquals(Collections.singletonList("test-role-member"), extractUsernames(roleUserMembers));
|
assertEquals(Collections.singletonList("test-role-member"), extractUsernames(roleUserMembers));
|
||||||
|
Assert.assertNotNull("Not in full representation", roleUserMembers.get(0).getNotBefore());
|
||||||
|
|
||||||
roleUserMembers = roleResource.getUserMembers(1, 1);
|
roleUserMembers = roleResource.getUserMembers(true, 1, 1);
|
||||||
assertThat(roleUserMembers, hasSize(1));
|
assertThat(roleUserMembers, hasSize(1));
|
||||||
assertEquals(Collections.singletonList("test-role-member2"), extractUsernames(roleUserMembers));
|
assertEquals(Collections.singletonList("test-role-member2"), extractUsernames(roleUserMembers));
|
||||||
|
Assert.assertNull("Not in brief representation", roleUserMembers.get(0).getNotBefore());
|
||||||
|
|
||||||
roleUserMembers = roleResource.getUserMembers(2, 1);
|
roleUserMembers = roleResource.getUserMembers(true, 2, 1);
|
||||||
assertThat(roleUserMembers, is(empty()));
|
assertThat(roleUserMembers, is(empty()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue