Add response annotations to resourceserver

Closes: #25604

Signed-off-by: Sophie Tauchert <sophie@999eagle.moe>
This commit is contained in:
Sophie Tauchert 2023-12-11 10:03:21 +01:00 committed by Alexander Schwartz
parent 14fd61bacc
commit 3ab24afe93
5 changed files with 117 additions and 14 deletions

View file

@ -33,9 +33,15 @@ import java.util.stream.Stream;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status; 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.jboss.logging.Logger;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
import org.keycloak.authorization.AuthorizationProvider; 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.AuthorizationRequest;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.representations.idm.authorization.PolicyEvaluationRequest; 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.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ScopeRepresentation; import org.keycloak.representations.idm.authorization.ScopeRepresentation;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.Urls; import org.keycloak.services.Urls;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.UserSessionManager; import org.keycloak.services.managers.UserSessionManager;
import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.sessions.AuthenticationSessionModel;
/** /**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
@Extension(name = KeycloakOpenAPI.Profiles.ADMIN, value = "")
public class PolicyEvaluationService { public class PolicyEvaluationService {
private static final Logger logger = Logger.getLogger(PolicyEvaluationService.class); private static final Logger logger = Logger.getLogger(PolicyEvaluationService.class);
@ -92,8 +101,15 @@ public class PolicyEvaluationService {
} }
@POST @POST
@Consumes("application/json") @Consumes(MediaType.APPLICATION_JSON)
@Produces("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) { public Response evaluate(PolicyEvaluationRequest evaluationRequest) {
this.auth.realm().requireViewAuthorization(); this.auth.realm().requireViewAuthorization();
CloseableKeycloakIdentity identity = createIdentity(evaluationRequest); CloseableKeycloakIdentity identity = createIdentity(evaluationRequest);

View file

@ -35,7 +35,12 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status; 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.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.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.authorization.AuthorizationProvider; import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy; import org.keycloak.authorization.model.Policy;
@ -105,6 +110,7 @@ public class PolicyService {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@NoCache @NoCache
@APIResponse(responseCode = "201", description = "Created")
public Response create(String payload) { public Response create(String payload) {
if (auth != null) { if (auth != null) {
this.auth.realm().requireManageAuthorization(); this.auth.realm().requireManageAuthorization();
@ -147,6 +153,14 @@ public class PolicyService {
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@NoCache @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) { public Response findByName(@QueryParam("name") String name, @QueryParam("fields") String fields) {
if (auth != null) { if (auth != null) {
this.auth.realm().requireViewAuthorization(); this.auth.realm().requireViewAuthorization();
@ -170,6 +184,13 @@ public class PolicyService {
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@NoCache @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, public Response findAll(@QueryParam("policyId") String id,
@QueryParam("name") String name, @QueryParam("name") String name,
@QueryParam("type") String type, @QueryParam("type") String type,
@ -274,6 +295,10 @@ public class PolicyService {
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@NoCache @NoCache
@APIResponse(
responseCode = "200",
content = @Content(schema = @Schema(implementation = PolicyProviderRepresentation.class, type = SchemaType.ARRAY))
)
public Response findPolicyProviders() { public Response findPolicyProviders() {
if (auth != null) { if (auth != null) {
this.auth.realm().requireViewAuthorization(); this.auth.realm().requireViewAuthorization();

View file

@ -125,9 +125,9 @@ public class ResourceServerService {
@Path("/settings") @Path("/settings")
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response exportSettings() { public ResourceServerRepresentation exportSettings() {
this.auth.realm().requireManageAuthorization(); this.auth.realm().requireManageAuthorization();
return Response.ok(ModelToRepresentation.toResourceServerRepresentation(session, client)).build(); return ModelToRepresentation.toResourceServerRepresentation(session, client);
} }
@Path("/import") @Path("/import")

View file

@ -41,10 +41,16 @@ import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status; 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.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.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
import org.keycloak.authorization.AuthorizationProvider; import org.keycloak.authorization.AuthorizationProvider;
@ -94,8 +100,15 @@ public class ResourceSetService {
@POST @POST
@NoCache @NoCache
@Consumes("application/json") @Consumes(MediaType.APPLICATION_JSON)
@Produces("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) { public Response createPost(ResourceRepresentation resource) {
if (resource == null) { if (resource == null) {
return Response.status(Status.BAD_REQUEST).build(); return Response.status(Status.BAD_REQUEST).build();
@ -136,8 +149,12 @@ public class ResourceSetService {
@Path("{resource-id}") @Path("{resource-id}")
@PUT @PUT
@Consumes("application/json") @Consumes(MediaType.APPLICATION_JSON)
@Produces("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) { public Response update(@PathParam("resource-id") String id, ResourceRepresentation resource) {
requireManage(); requireManage();
resource.setId(id); resource.setId(id);
@ -158,6 +175,10 @@ public class ResourceSetService {
@Path("{resource-id}") @Path("{resource-id}")
@DELETE @DELETE
@APIResponses(value = {
@APIResponse(responseCode = "204", description = "No Content"),
@APIResponse(responseCode = "404", description = "Not Found")
})
public Response delete(@PathParam("resource-id") String id) { public Response delete(@PathParam("resource-id") String id) {
requireManage(); requireManage();
StoreFactory storeFactory = authorization.getStoreFactory(); StoreFactory storeFactory = authorization.getStoreFactory();
@ -180,7 +201,14 @@ public class ResourceSetService {
@Path("{resource-id}") @Path("{resource-id}")
@GET @GET
@NoCache @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) { public Response findById(@PathParam("resource-id") String id) {
return findById(id, resource -> toRepresentation(resource, resourceServer, authorization, true)); return findById(id, resource -> toRepresentation(resource, resourceServer, authorization, true));
} }
@ -200,7 +228,14 @@ public class ResourceSetService {
@Path("{resource-id}/scopes") @Path("{resource-id}/scopes")
@GET @GET
@NoCache @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) { public Response getScopes(@PathParam("resource-id") String id) {
requireView(); requireView();
StoreFactory storeFactory = authorization.getStoreFactory(); StoreFactory storeFactory = authorization.getStoreFactory();
@ -243,7 +278,14 @@ public class ResourceSetService {
@Path("{resource-id}/permissions") @Path("{resource-id}/permissions")
@GET @GET
@NoCache @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) { public Response getPermissions(@PathParam("resource-id") String id) {
requireView(); requireView();
StoreFactory storeFactory = authorization.getStoreFactory(); StoreFactory storeFactory = authorization.getStoreFactory();
@ -301,7 +343,7 @@ public class ResourceSetService {
@Path("{resource-id}/attributes") @Path("{resource-id}/attributes")
@GET @GET
@NoCache @NoCache
@Produces("application/json") @Produces(MediaType.APPLICATION_JSON)
public Response getAttributes(@PathParam("resource-id") String id) { public Response getAttributes(@PathParam("resource-id") String id) {
requireView(); requireView();
StoreFactory storeFactory = authorization.getStoreFactory(); StoreFactory storeFactory = authorization.getStoreFactory();
@ -317,7 +359,15 @@ public class ResourceSetService {
@Path("/search") @Path("/search")
@GET @GET
@NoCache @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) { public Response find(@QueryParam("name") String name) {
this.auth.realm().requireViewAuthorization(); this.auth.realm().requireViewAuthorization();
StoreFactory storeFactory = authorization.getStoreFactory(); StoreFactory storeFactory = authorization.getStoreFactory();
@ -337,7 +387,11 @@ public class ResourceSetService {
@GET @GET
@NoCache @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, public Response find(@QueryParam("_id") String id,
@QueryParam("name") String name, @QueryParam("name") String name,
@QueryParam("uri") String uri, @QueryParam("uri") String uri,

View file

@ -249,6 +249,14 @@ public class ScopeService {
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@NoCache @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) { public Response find(@QueryParam("name") String name) {
this.auth.realm().requireViewAuthorization(); this.auth.realm().requireViewAuthorization();
StoreFactory storeFactory = authorization.getStoreFactory(); StoreFactory storeFactory = authorization.getStoreFactory();