getUsers(
+ @Parameter(description = "A String contained in username, first or last name, or email") @QueryParam("search") String search,
+ @Parameter(description = "A String contained in lastName, or the complete lastName, if param \"exact\" is true") @QueryParam("lastName") String last,
+ @Parameter(description = "A String contained in firstName, or the complete firstName, if param \"exact\" is true") @QueryParam("firstName") String first,
+ @Parameter(description = "A String contained in email, or the complete email, if param \"exact\" is true") @QueryParam("email") String email,
+ @Parameter(description = "A String contained in username, or the complete username, if param \"exact\" is true") @QueryParam("username") String username,
+ @Parameter(description = "whether the email has been verified") @QueryParam("emailVerified") Boolean emailVerified,
+ @Parameter(description = "The alias of an Identity Provider linked to the user") @QueryParam("idpAlias") String idpAlias,
+ @Parameter(description = "The userId at an Identity Provider linked to the user") @QueryParam("idpUserId") String idpUserId,
+ @Parameter(description = "Pagination offset") @QueryParam("first") Integer firstResult,
+ @Parameter(description = "Maximum results size (defaults to 100)") @QueryParam("max") Integer maxResults,
+ @Parameter(description = "Boolean representing if user is enabled or not") @QueryParam("enabled") Boolean enabled,
+ @Parameter(description = "Boolean which defines whether brief representations are returned (default: false)") @QueryParam("briefRepresentation") Boolean briefRepresentation,
+ @Parameter(description = "Boolean which defines whether the params \"last\", \"first\", \"email\" and \"username\" must match exactly") @QueryParam("exact") Boolean exact,
+ @Parameter(description = "A query to search for custom attributes, in the format 'key1:value2 key2:value2'") @QueryParam("q") String searchQuery) {
UserPermissionEvaluator userPermissionEvaluator = auth.users();
userPermissionEvaluator.requireQuery();
@@ -364,14 +375,22 @@ public class UsersResource {
@GET
@NoCache
@Produces(MediaType.APPLICATION_JSON)
- public Integer getUsersCount(@QueryParam("search") String search,
- @QueryParam("lastName") String last,
- @QueryParam("firstName") String first,
- @QueryParam("email") String email,
- @QueryParam("emailVerified") Boolean emailVerified,
- @QueryParam("username") String username,
- @QueryParam("enabled") Boolean enabled,
- @QueryParam("q") String searchQuery) {
+ @Tag(name = KeycloakOpenAPI.Admin.Tags.USERS)
+ @Operation(
+ summary = "Returns the number of users that match the given criteria.",
+ description = "It can be called in three different ways. " +
+ "1. Don’t specify any criteria and pass {@code null}. The number of all users within that realm will be returned. " +
+ "2. If {@code search} is specified other criteria such as {@code last} will be ignored even though you set them. The {@code search} string will be matched against the first and last name, the username and the email of a user.
" +
+ "3. If {@code search} is unspecified but any of {@code last}, {@code first}, {@code email} or {@code username} those criteria are matched against their respective fields on a user entity. Combined with a logical and.")
+ public Integer getUsersCount(
+ @Parameter(description = "arbitrary search string for all the fields below") @QueryParam("search") String search,
+ @Parameter(description = "last name filter") @QueryParam("lastName") String last,
+ @Parameter(description = "first name filter") @QueryParam("firstName") String first,
+ @Parameter(description = "email filter") @QueryParam("email") String email,
+ @QueryParam("emailVerified") Boolean emailVerified,
+ @Parameter(description = "username filter") @QueryParam("username") String username,
+ @Parameter(description = "Boolean representing if user is enabled or not") @QueryParam("enabled") Boolean enabled,
+ @QueryParam("q") String searchQuery) {
UserPermissionEvaluator userPermissionEvaluator = auth.users();
userPermissionEvaluator.requireQuery();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
index c01cb5b058c..9278e886172 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
@@ -17,6 +17,9 @@
package org.keycloak.services.resources.admin.info;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.extensions.Extension;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
@@ -53,6 +56,7 @@ import org.keycloak.representations.info.ServerInfoRepresentation;
import org.keycloak.representations.info.SpiInfoRepresentation;
import org.keycloak.representations.info.SystemInfoRepresentation;
import org.keycloak.representations.info.ThemeInfoRepresentation;
+import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.theme.Theme;
import jakarta.ws.rs.GET;
@@ -74,6 +78,7 @@ import java.util.stream.Stream;
/**
* @author Stian Thorgersen
*/
+@Extension(name = KeycloakOpenAPI.Profiles.ADMIN , value = "")
public class ServerInfoAdminResource {
private static final Map> ENUMS = createEnumsMap(EventType.class, OperationType.class, ResourceType.class);
@@ -92,6 +97,8 @@ public class ServerInfoAdminResource {
@GET
@NoCache
@Produces(MediaType.APPLICATION_JSON)
+ @Tag(name = KeycloakOpenAPI.Admin.Tags.ROOT)
+ @Operation( summary = "Get themes, social providers, auth providers, and event listeners available on this server")
public ServerInfoRepresentation getInfo() {
ServerInfoRepresentation info = new ServerInfoRepresentation();
info.setSystemInfo(SystemInfoRepresentation.create(session.getKeycloakSessionFactory().getServerStartupTimestamp()));