10000 Added new searchByAttributes function to UsersResource with the exact parameter by Michael-AT-Corporation · Pull Request #40168 · keycloak/keycloak · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Added new searchByAttributes function to UsersResource with the exact parameter #40168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docs/documentation/upgrading/topics/changes/changes-26_4_0.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
== Breaking changes

Breaking changes are identified as requiring changes from existing users to their configurations.
In minor or patch releases we will only do breaking changes to fix bugs.

=== <TODO>

== Notable changes

Notable changes where an internal behavior changed to prevent common misconfigurations, fix bugs or simplify running {project_name}.

=== Usage of the `exact` request parameter when searching users by attributes

If you are querying users by attributes through the User API where you want to fetch users that match a specific attribute key (regardless the value),
you should consider setting the `exact` request parameter to `false` when invoking the `/admin/realms/{realm}/users` using
the `GET` method.

For instance, searching for all users with the attribute `myattribute` set should be done as follows:

```
GET /admin/realms/{realm}/users?exact=false&q=myattribute:
```

The {project_name} Admin Client is also updated with a new method to search users by attribute using the `exact` request parameter.

== Deprecated features

The following sections provide details on deprecated features.

=== <TODO>

== Removed features

The following features have been removed from this release.

=== <TODO>
4 changes: 2 additions & 2 deletions docs/documentation/upgrading/topics/changes/changes.adoc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[[migration-changes]]
== Migration Changes

=== Migrating to 26.3.1
=== Migrating to 26.4.0

include::changes-26_3_1.adoc[leveloffset=2]
include::changes-26_4_0.adoc[leveloffset=2]

=== Migrating to 26.3.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,16 @@ List<UserRepresentation> searchByAttributes(@QueryParam("first") Integer firstRe
@QueryParam("briefRepresentation") Boolean briefRepresentation,
@QueryParam("q") String searchQuery);

@GET
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
List<UserRepresentation> searchByAttributes(@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults,
@QueryParam("enabled") Boolean enabled,
@QueryParam("exact") Boolean exact,
@QueryParam("briefRepresentation") Boolean briefRepresentation,
@QueryParam("q") String searchQuery);

@GET
@Produces(MediaType.APPLICATION_JSON)
List<UserRepresentation> search(@QueryParam("username") String username, @QueryParam("exact") Boolean exact);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -961,6 +962,33 @@ public void searchByAttributesWithPagination() {
}
}

@Test
public void searchByAttributesForAnyValue() {
createUser(UserBuilder.create().username("user-0").addAttribute("attr", "common").build());
createUser(UserBuilder.create().username("user-1").addAttribute("test", "common").build());
createUser(UserBuilder.create().username("user-2").addAttribute("test", "common").addAttribute("attr", "common").build());

Map<String, String> attributes = new HashMap<>();
attributes.put("attr", "");
// exact needs to be set to false to match for any users with the attribute attr
List<UserRepresentation> users = realm.users().searchByAttributes(-1, -1, null, false, false, mapToSearchQuery(attributes));
assertEquals(2, users.size());
assertTrue(users.stream().allMatch(r -> Set.of("user-0", "user-2").contains(r.getUsername())));

attributes = new HashMap<>();
attributes.put("test", "");
users = realm.users().searchByAttributes(-1, -1, null, false, false, mapToSearchQuery(attributes));
assertEquals(2, users.size());
assertTrue(users.stream().allMatch(r -> Set.of("user-1", "user-2").contains(r.getUsername())));

attributes = new HashMap<>();
attributes.put("test", "");
attributes.put("attr", "");
users = realm.users().searchByAttributes(-1, -1, null, false, false, mapToSearchQuery(attributes));
assertEquals(1, users.size());
assertTrue(users.stream().allMatch(r -> "user-2".equals(r.getUsername())));
}

@Test
public void storeAndReadUserWithLongAttributeValue() {
String longValue = RandomStringUtils.random(Integer.parseInt(DefaultAttributes.DEFAULT_MAX_LENGTH_ATTRIBUTES), true, true);
Expand Down
Loading
0