1 package de.dlr.shepard.auth.apikey.endpoints; 2 3 import de.dlr.shepard.auth.apikey.entities.ApiKey; 4 import de.dlr.shepard.auth.apikey.io.ApiKeyIO; 5 import de.dlr.shepard.auth.apikey.io.ApiKeyWithJWTIO; 6 import de.dlr.shepard.auth.apikey.services.ApiKeyService; 7 import de.dlr.shepard.common.exceptions.InvalidRequestException; 8 import de.dlr.shepard.common.util.Constants; 9 import io.quarkus.logging.Log; 10 import jakarta.enterprise.context.RequestScoped; 11 import jakarta.inject.Inject; 12 import jakarta.validation.Valid; 13 import jakarta.validation.constraints.NotBlank; 14 import jakarta.ws.rs.Consumes; 15 import jakarta.ws.rs.DELETE; 16 import jakarta.ws.rs.GET; 17 import jakarta.ws.rs.POST; 18 import jakarta.ws.rs.Path; 19 import jakarta.ws.rs.PathParam; 20 import jakarta.ws.rs.Produces; 21 import jakarta.ws.rs.core.Context; 22 import jakarta.ws.rs.core.MediaType; 23 import jakarta.ws.rs.core.Response; 24 import jakarta.ws.rs.core.Response.Status; 25 import jakarta.ws.rs.core.UriInfo; 26 import java.util.ArrayList; 27 import java.util.UUID; 28 import org.eclipse.microprofile.openapi.annotations.Operation; 29 import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; 30 import org.eclipse.microprofile.openapi.annotations.media.Content; 31 import org.eclipse.microprofile.openapi.annotations.media.Schema; 32 import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; 33 import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; 34 import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; 35 import org.eclipse.microprofile.openapi.annotations.tags.Tag; 36 37 @Produces(MediaType.APPLICATION_JSON) 38 @Consumes(MediaType.APPLICATION_JSON) 39 @Path(Constants.USERS + "/{" + Constants.USERNAME + "}/" + Constants.APIKEYS) 40 @RequestScoped 41 public class ApiKeyRest { 42 43 @Inject 44 ApiKeyService apiKeyService; 45 46 @Context 47 private UriInfo uriInfo; 48 49 @GET 50 @Tag(name = Constants.APIKEY) 51 @Operation(description = "Get all api keys") 52 @APIResponse( 53 description = "ok", 54 responseCode = "200", 55 content = @Content( 56 schema = @Schema(description = "The search result page", type = SchemaType.ARRAY, implementation = ApiKeyIO.class) 57 ) 58 ) 59 @APIResponse(description = "bad request", responseCode = "400") 60 @APIResponse(description = "not authorized", responseCode = "401") 61 @APIResponse(description = "forbidden", responseCode = "403") 62 @Parameter(name = Constants.USERNAME, required = true) 63 public Response getAllApiKeys(@PathParam(Constants.USERNAME) @NotBlank String username) { 64 var apiKeys = apiKeyService.getAllApiKeys(username); 65 var result = new ArrayList<ApiKeyIO>(apiKeys.size()); 66 67 for (var key : apiKeys) { 68 result.add(new ApiKeyIO(key)); 69 } 70 return Response.ok(result).build(); 71 } 72 73 @GET 74 @Path("/{" + Constants.APIKEY_UID + "}") 75 @Tag(name = Constants.APIKEY) 76 @Operation(description = "Get api key") 77 @APIResponse( 78 description = "ok", 79 responseCode = "200", 80 content = @Content(schema = @Schema(implementation = ApiKeyIO.class)) 81 ) 82 @APIResponse(description = "bad request", responseCode = "400") 83 @APIResponse(description = "not authorized", responseCode = "401") 84 @APIResponse(description = "forbidden", responseCode = "403") 85 @Parameter(name = Constants.USERNAME, required = true) 86 @Parameter(name = Constants.APIKEY_UID, required = true) 87 public Response getApiKey( 88 @PathParam(Constants.USERNAME) @NotBlank String username, 89 @PathParam(Constants.APIKEY_UID) @NotBlank @org.hibernate.validator.constraints.UUID String apiKeyUid 90 ) { 91 UUID uid; 92 try { 93 uid = UUID.fromString(apiKeyUid); 94 } catch (IllegalArgumentException e) { 95 Log.errorf("The given api key uid has an invalid format: %s", apiKeyUid); 96 throw new InvalidRequestException("The given api key uid has an invalid format"); 97 } 98 ApiKey apiKey = apiKeyService.getApiKey(username, uid); 99 return Response.ok(new ApiKeyIO(apiKey)).build(); 100 } 101 102 @POST 103 @Tag(name = Constants.APIKEY) 104 @Operation(description = "Create a new api key") 105 @APIResponse( 106 description = "created", 107 responseCode = "201", 108 content = @Content(schema = @Schema(implementation = ApiKeyWithJWTIO.class)) 109 ) 110 @APIResponse(description = "not found", responseCode = "404") 111 @APIResponse(description = "bad request", responseCode = "400") 112 @APIResponse(description = "not authorized", responseCode = "401") 113 @APIResponse(description = "forbidden", responseCode = "403") 114 @Parameter(name = Constants.USERNAME, required = true) 115 public Response createApiKey( 116 @PathParam(Constants.USERNAME) @NotBlank String username, 117 @RequestBody( 118 required = true, 119 content = @Content(schema = @Schema(implementation = ApiKeyIO.class)) 120 ) @Valid ApiKeyIO apiKey 121 ) { 122 ApiKey created = apiKeyService.createApiKey(apiKey, username, uriInfo.getBaseUri().toString()); 123 return Response.ok(new ApiKeyWithJWTIO(created)).status(Status.CREATED).build(); 124 } 125 126 @DELETE 127 @Path("/{" + Constants.APIKEY_UID + "}") 128 @Tag(name = Constants.APIKEY) 129 @Operation(description = "Delete api key") 130 @APIResponse(description = "deleted", responseCode = "204") 131 @APIResponse(description = "not found", responseCode = "404") 132 @APIResponse(description = "bad request", responseCode = "400") 133 @APIResponse(description = "not authorized", responseCode = "401") 134 @APIResponse(description = "forbidden", responseCode = "403") 135 @Parameter(name = Constants.USERNAME, required = true) 136 @Parameter(name = Constants.APIKEY_UID, required = true) 137 public Response deleteApiKey( 138 @PathParam(Constants.USERNAME) @NotBlank String username, 139 @PathParam(Constants.APIKEY_UID) @NotBlank @org.hibernate.validator.constraints.UUID String apiKeyUid 140 ) { 141 UUID uid; 142 try { 143 uid = UUID.fromString(apiKeyUid); 144 } catch (IllegalArgumentException e) { 145 Log.errorf("The given api key uid has an invalid format: %s", apiKeyUid); 146 throw new InvalidRequestException("The given api key uid has an invalid format"); 147 } 148 return apiKeyService.deleteApiKey(username, uid) 149 ? Response.status(Status.NO_CONTENT).build() 150 : Response.status(Status.INTERNAL_SERVER_ERROR).build(); 151 } 152 }