[KEYCLOAK-14282] Create additional filtering for GET /users endpoint for enabled/disabled users
This commit is contained in:
parent
6abae8bccc
commit
914b226d11
6 changed files with 74 additions and 2 deletions
|
@ -50,6 +50,7 @@ public interface UsersResource {
|
||||||
@QueryParam("email") String email,
|
@QueryParam("email") String email,
|
||||||
@QueryParam("first") Integer firstResult,
|
@QueryParam("first") Integer firstResult,
|
||||||
@QueryParam("max") Integer maxResults,
|
@QueryParam("max") Integer maxResults,
|
||||||
|
@QueryParam("enabled") Boolean enabled,
|
||||||
@QueryParam("briefRepresentation") Boolean briefRepresentation);
|
@QueryParam("briefRepresentation") Boolean briefRepresentation);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
|
|
@ -870,10 +870,13 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
case LAST_NAME:
|
case LAST_NAME:
|
||||||
case EMAIL:
|
case EMAIL:
|
||||||
if (Boolean.valueOf(attributes.getOrDefault(UserModel.EXACT, Boolean.FALSE.toString()))) {
|
if (Boolean.valueOf(attributes.getOrDefault(UserModel.EXACT, Boolean.FALSE.toString()))) {
|
||||||
predicates.add(builder.equal(builder.lower(root.get(key)), value.toLowerCase()));
|
predicates.add(builder.equal(builder.lower(root.get(key)), value.toLowerCase()));
|
||||||
} else {
|
} else {
|
||||||
predicates.add(builder.like(builder.lower(root.get(key)), "%" + value.toLowerCase() + "%"));
|
predicates.add(builder.like(builder.lower(root.get(key)), "%" + value.toLowerCase() + "%"));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case UserModel.ENABLED:
|
||||||
|
predicates.add(builder.equal(builder.lower(root.get(key)), Boolean.parseBoolean(value.toLowerCase())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ public interface UserModel extends RoleMapperModel {
|
||||||
String LAST_NAME = "lastName";
|
String LAST_NAME = "lastName";
|
||||||
String EMAIL = "email";
|
String EMAIL = "email";
|
||||||
String LOCALE = "locale";
|
String LOCALE = "locale";
|
||||||
|
String ENABLED = "enabled";
|
||||||
String INCLUDE_SERVICE_ACCOUNT = "keycloak.session.realm.users.query.include_service_account";
|
String INCLUDE_SERVICE_ACCOUNT = "keycloak.session.realm.users.query.include_service_account";
|
||||||
String GROUPS = "keycloak.session.realm.users.query.groups";
|
String GROUPS = "keycloak.session.realm.users.query.groups";
|
||||||
String SEARCH = "keycloak.session.realm.users.query.search";
|
String SEARCH = "keycloak.session.realm.users.query.search";
|
||||||
|
|
|
@ -204,6 +204,7 @@ public interface UserQueryProvider {
|
||||||
* "last" - last name
|
* "last" - last name
|
||||||
* "email" - email
|
* "email" - email
|
||||||
* "username" - username
|
* "username" - username
|
||||||
|
* "enabled" - is user enabled (true/false)
|
||||||
*
|
*
|
||||||
* If possible, implementations should treat the parameter values as patterns i.e. in RDMBS terms use LIKE.
|
* If possible, implementations should treat the parameter values as patterns i.e. in RDMBS terms use LIKE.
|
||||||
* This method is used by the REST API when querying users.
|
* This method is used by the REST API when querying users.
|
||||||
|
|
|
@ -189,6 +189,7 @@ public class UsersResource {
|
||||||
* @param first
|
* @param first
|
||||||
* @param email
|
* @param email
|
||||||
* @param username
|
* @param username
|
||||||
|
* @param enabled Boolean representing if user is enabled or not
|
||||||
* @param first Pagination offset
|
* @param first Pagination offset
|
||||||
* @param maxResults Maximum results size (defaults to 100)
|
* @param maxResults Maximum results size (defaults to 100)
|
||||||
* @return
|
* @return
|
||||||
|
@ -203,6 +204,7 @@ public class UsersResource {
|
||||||
@QueryParam("username") String username,
|
@QueryParam("username") String username,
|
||||||
@QueryParam("first") Integer firstResult,
|
@QueryParam("first") Integer firstResult,
|
||||||
@QueryParam("max") Integer maxResults,
|
@QueryParam("max") Integer maxResults,
|
||||||
|
@QueryParam("enabled") Boolean enabled,
|
||||||
@QueryParam("briefRepresentation") Boolean briefRepresentation,
|
@QueryParam("briefRepresentation") Boolean briefRepresentation,
|
||||||
@QueryParam("exact") Boolean exact) {
|
@QueryParam("exact") Boolean exact) {
|
||||||
UserPermissionEvaluator userPermissionEvaluator = auth.users();
|
UserPermissionEvaluator userPermissionEvaluator = auth.users();
|
||||||
|
@ -222,6 +224,9 @@ public class UsersResource {
|
||||||
} else {
|
} else {
|
||||||
Map<String, String> attributes = new HashMap<>();
|
Map<String, String> attributes = new HashMap<>();
|
||||||
attributes.put(UserModel.SEARCH, search.trim());
|
attributes.put(UserModel.SEARCH, search.trim());
|
||||||
|
if (enabled != null) {
|
||||||
|
attributes.put(UserModel.ENABLED, enabled.toString());
|
||||||
|
}
|
||||||
return searchForUser(attributes, realm, userPermissionEvaluator, briefRepresentation, firstResult, maxResults, false);
|
return searchForUser(attributes, realm, userPermissionEvaluator, briefRepresentation, firstResult, maxResults, false);
|
||||||
}
|
}
|
||||||
} else if (last != null || first != null || email != null || username != null) {
|
} else if (last != null || first != null || email != null || username != null) {
|
||||||
|
@ -238,6 +243,9 @@ public class UsersResource {
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
attributes.put(UserModel.USERNAME, username);
|
attributes.put(UserModel.USERNAME, username);
|
||||||
}
|
}
|
||||||
|
if (enabled != null) {
|
||||||
|
attributes.put(UserModel.ENABLED, enabled.toString());
|
||||||
|
}
|
||||||
if (exact != null) {
|
if (exact != null) {
|
||||||
attributes.put(UserModel.EXACT, exact.toString());
|
attributes.put(UserModel.EXACT, exact.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.admin.client.resource.RoleMappingResource;
|
import org.keycloak.admin.client.resource.RoleMappingResource;
|
||||||
import org.keycloak.admin.client.resource.UserResource;
|
import org.keycloak.admin.client.resource.UserResource;
|
||||||
import org.keycloak.admin.client.resource.UsersResource;
|
import org.keycloak.admin.client.resource.UsersResource;
|
||||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
import org.keycloak.common.util.Base64;
|
import org.keycloak.common.util.Base64;
|
||||||
import org.keycloak.common.util.ObjectUtil;
|
import org.keycloak.common.util.ObjectUtil;
|
||||||
|
@ -626,6 +625,65 @@ public class UserTest extends AbstractAdminTest {
|
||||||
assertEquals(1, users.size());
|
assertEquals(1, users.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchByEnabled() {
|
||||||
|
String userCommonName = "enabled-disabled-user";
|
||||||
|
|
||||||
|
UserRepresentation user1 = new UserRepresentation();
|
||||||
|
user1.setUsername(userCommonName + "1");
|
||||||
|
user1.setRequiredActions(Collections.emptyList());
|
||||||
|
user1.setEnabled(true);
|
||||||
|
createUser(user1);
|
||||||
|
|
||||||
|
UserRepresentation user2 = new UserRepresentation();
|
||||||
|
user2.setUsername(userCommonName + "2");
|
||||||
|
user2.setRequiredActions(Collections.emptyList());
|
||||||
|
user2.setEnabled(false);
|
||||||
|
createUser(user2);
|
||||||
|
|
||||||
|
List<UserRepresentation> enabledUsers = realm.users().search(null, null, null, null, null, null, true, false);
|
||||||
|
assertEquals(1, enabledUsers.size());
|
||||||
|
|
||||||
|
List<UserRepresentation> enabledUsersWithFilter = realm.users().search(userCommonName, null, null, null, null, null, true, true);
|
||||||
|
assertEquals(1, enabledUsersWithFilter.size());
|
||||||
|
assertEquals(user1.getUsername(), enabledUsersWithFilter.get(0).getUsername());
|
||||||
|
|
||||||
|
List<UserRepresentation> disabledUsers = realm.users().search(userCommonName, null, null, null, null, null, false, false);
|
||||||
|
assertEquals(1, disabledUsers.size());
|
||||||
|
assertEquals(user2.getUsername(), disabledUsers.get(0).getUsername());
|
||||||
|
|
||||||
|
List<UserRepresentation> allUsers = realm.users().search(userCommonName, null, null, null, 0, 100, null, true);
|
||||||
|
assertEquals(2, allUsers.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchWithFilters() {
|
||||||
|
createUser();
|
||||||
|
|
||||||
|
UserRepresentation user = new UserRepresentation();
|
||||||
|
user.setUsername("user2");
|
||||||
|
user.setFirstName("First");
|
||||||
|
user.setLastName("Last");
|
||||||
|
user.setEmail("user2@localhost");
|
||||||
|
user.setRequiredActions(Collections.emptyList());
|
||||||
|
user.setEnabled(false);
|
||||||
|
createUser(user);
|
||||||
|
|
||||||
|
List<UserRepresentation> searchFirstNameAndDisabled = realm.users().search(null, "First", null, null, null, null, false, true);
|
||||||
|
assertEquals(1, searchFirstNameAndDisabled.size());
|
||||||
|
assertEquals(user.getUsername(), searchFirstNameAndDisabled.get(0).getUsername());
|
||||||
|
|
||||||
|
List<UserRepresentation> searchLastNameAndEnabled = realm.users().search(null, null, "Last", null, null, null, true, false);
|
||||||
|
assertEquals(0, searchLastNameAndEnabled.size());
|
||||||
|
|
||||||
|
List<UserRepresentation> searchEmailAndDisabled = realm.users().search(null, null, null, "user2@localhost", 0, 50, false, true);
|
||||||
|
assertEquals(1, searchEmailAndDisabled.size());
|
||||||
|
assertEquals(user.getUsername(), searchEmailAndDisabled.get(0).getUsername());
|
||||||
|
|
||||||
|
List<UserRepresentation> searchInvalidSizeAndDisabled = realm.users().search(null, null, null, null, 10, 20, null, false);
|
||||||
|
assertEquals(0, searchInvalidSizeAndDisabled.size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void searchById() {
|
public void searchById() {
|
||||||
String expectedUserId = createUsers().get(0);
|
String expectedUserId = createUsers().get(0);
|
||||||
|
|
Loading…
Reference in a new issue