diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java index 8a13d6b96a..f9f1385da9 100644 --- a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java +++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java @@ -33,9 +33,15 @@ import java.util.stream.Stream; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.POST; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status; +import org.eclipse.microprofile.openapi.annotations.extensions.Extension; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.jboss.logging.Logger; import org.keycloak.OAuthErrorException; import org.keycloak.authorization.AuthorizationProvider; @@ -65,18 +71,21 @@ import org.keycloak.representations.AccessToken; import org.keycloak.representations.idm.authorization.AuthorizationRequest; import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.PolicyEvaluationRequest; +import org.keycloak.representations.idm.authorization.PolicyEvaluationResponse; import org.keycloak.representations.idm.authorization.ResourceRepresentation; import org.keycloak.representations.idm.authorization.ScopeRepresentation; import org.keycloak.services.ErrorResponseException; import org.keycloak.services.Urls; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.UserSessionManager; +import org.keycloak.services.resources.KeycloakOpenAPI; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.sessions.AuthenticationSessionModel; /** * @author Pedro Igor */ +@Extension(name = KeycloakOpenAPI.Profiles.ADMIN, value = "") public class PolicyEvaluationService { private static final Logger logger = Logger.getLogger(PolicyEvaluationService.class); @@ -92,8 +101,15 @@ public class PolicyEvaluationService { } @POST - @Consumes("application/json") - @Produces("application/json") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = PolicyEvaluationResponse.class)) + ), + @APIResponse(responseCode = "500", description = "Internal Server Error") + }) public Response evaluate(PolicyEvaluationRequest evaluationRequest) { this.auth.realm().requireViewAuthorization(); CloseableKeycloakIdentity identity = createIdentity(evaluationRequest); diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java index c0ed229a48..6534c14cdc 100644 --- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java +++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java @@ -35,7 +35,12 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.extensions.Extension; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.jboss.resteasy.annotations.cache.NoCache; import org.keycloak.authorization.AuthorizationProvider; import org.keycloak.authorization.model.Policy; @@ -105,6 +110,7 @@ public class PolicyService { @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @NoCache + @APIResponse(responseCode = "201", description = "Created") public Response create(String payload) { if (auth != null) { this.auth.realm().requireManageAuthorization(); @@ -147,6 +153,14 @@ public class PolicyService { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = AbstractPolicyRepresentation.class)) + ), + @APIResponse(responseCode = "204", description = "No Content"), + @APIResponse(responseCode = "400", description = "Bad Request") + }) public Response findByName(@QueryParam("name") String name, @QueryParam("fields") String fields) { if (auth != null) { this.auth.realm().requireViewAuthorization(); @@ -170,6 +184,13 @@ public class PolicyService { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = AbstractPolicyRepresentation.class, type = SchemaType.ARRAY)) + ), + @APIResponse(responseCode = "204", description = "No Content") + }) public Response findAll(@QueryParam("policyId") String id, @QueryParam("name") String name, @QueryParam("type") String type, @@ -274,6 +295,10 @@ public class PolicyService { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = PolicyProviderRepresentation.class, type = SchemaType.ARRAY)) + ) public Response findPolicyProviders() { if (auth != null) { this.auth.realm().requireViewAuthorization(); diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java index 9a1f034d50..0231a5def2 100644 --- a/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java +++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceServerService.java @@ -125,9 +125,9 @@ public class ResourceServerService { @Path("/settings") @GET @Produces(MediaType.APPLICATION_JSON) - public Response exportSettings() { + public ResourceServerRepresentation exportSettings() { this.auth.realm().requireManageAuthorization(); - return Response.ok(ModelToRepresentation.toResourceServerRepresentation(session, client)).build(); + return ModelToRepresentation.toResourceServerRepresentation(session, client); } @Path("/import") diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java index 3e670206c1..1d3228f7cc 100644 --- a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java +++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java @@ -41,10 +41,16 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; import org.eclipse.microprofile.openapi.annotations.extensions.Extension; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.jboss.resteasy.annotations.cache.NoCache; import org.keycloak.OAuthErrorException; import org.keycloak.authorization.AuthorizationProvider; @@ -94,8 +100,15 @@ public class ResourceSetService { @POST @NoCache - @Consumes("application/json") - @Produces("application/json") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @APIResponses(value = { + @APIResponse( + responseCode = "201", description = "Created", + content = @Content(schema = @Schema(implementation = ResourceRepresentation.class)) + ), + @APIResponse(responseCode = "400", description = "Bad Request") + }) public Response createPost(ResourceRepresentation resource) { if (resource == null) { return Response.status(Status.BAD_REQUEST).build(); @@ -136,8 +149,12 @@ public class ResourceSetService { @Path("{resource-id}") @PUT - @Consumes("application/json") - @Produces("application/json") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @APIResponses(value = { + @APIResponse(responseCode = "204", description = "No Content"), + @APIResponse(responseCode = "404", description = "Not Found") + }) public Response update(@PathParam("resource-id") String id, ResourceRepresentation resource) { requireManage(); resource.setId(id); @@ -158,6 +175,10 @@ public class ResourceSetService { @Path("{resource-id}") @DELETE + @APIResponses(value = { + @APIResponse(responseCode = "204", description = "No Content"), + @APIResponse(responseCode = "404", description = "Not Found") + }) public Response delete(@PathParam("resource-id") String id) { requireManage(); StoreFactory storeFactory = authorization.getStoreFactory(); @@ -180,7 +201,14 @@ public class ResourceSetService { @Path("{resource-id}") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ResourceRepresentation.class)) + ), + @APIResponse(responseCode = "404", description = "Not found") + }) public Response findById(@PathParam("resource-id") String id) { return findById(id, resource -> toRepresentation(resource, resourceServer, authorization, true)); } @@ -200,7 +228,14 @@ public class ResourceSetService { @Path("{resource-id}/scopes") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ScopeRepresentation.class, type = SchemaType.ARRAY)) + ), + @APIResponse(responseCode = "404", description = "Not found") + }) public Response getScopes(@PathParam("resource-id") String id) { requireView(); StoreFactory storeFactory = authorization.getStoreFactory(); @@ -243,7 +278,14 @@ public class ResourceSetService { @Path("{resource-id}/permissions") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = PolicyRepresentation.class, type = SchemaType.ARRAY)) + ), + @APIResponse(responseCode = "404", description = "Not found") + }) public Response getPermissions(@PathParam("resource-id") String id) { requireView(); StoreFactory storeFactory = authorization.getStoreFactory(); @@ -301,7 +343,7 @@ public class ResourceSetService { @Path("{resource-id}/attributes") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) public Response getAttributes(@PathParam("resource-id") String id) { requireView(); StoreFactory storeFactory = authorization.getStoreFactory(); @@ -317,7 +359,15 @@ public class ResourceSetService { @Path("/search") @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ResourceRepresentation.class)) + ), + @APIResponse(responseCode = "400", description = "Bad Request"), + @APIResponse(responseCode = "204", description = "No Content") + }) public Response find(@QueryParam("name") String name) { this.auth.realm().requireViewAuthorization(); StoreFactory storeFactory = authorization.getStoreFactory(); @@ -337,7 +387,11 @@ public class ResourceSetService { @GET @NoCache - @Produces("application/json") + @Produces(MediaType.APPLICATION_JSON) + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ResourceRepresentation.class, type = SchemaType.ARRAY)) + ) public Response find(@QueryParam("_id") String id, @QueryParam("name") String name, @QueryParam("uri") String uri, diff --git a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java index 2830690013..192fb58e04 100644 --- a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java +++ b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java @@ -249,6 +249,14 @@ public class ScopeService { @GET @Produces(MediaType.APPLICATION_JSON) @NoCache + @APIResponses(value = { + @APIResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ScopeRepresentation.class, type = SchemaType.ARRAY)) + ), + @APIResponse(responseCode = "204", description = "No Content"), + @APIResponse(responseCode = "400", description = "Bad Request") + }) public Response find(@QueryParam("name") String name) { this.auth.realm().requireViewAuthorization(); StoreFactory storeFactory = authorization.getStoreFactory();