diff --git a/src/main/java/org/dependencytrack/model/Component.java b/src/main/java/org/dependencytrack/model/Component.java index e7e02e22f..fc1d632ba 100644 --- a/src/main/java/org/dependencytrack/model/Component.java +++ b/src/main/java/org/dependencytrack/model/Component.java @@ -618,6 +618,7 @@ public void setPurl(String purl) { } @JsonSerialize(using = CustomPackageURLSerializer.class) + @ApiModelProperty(dataType = "string", accessMode = ApiModelProperty.AccessMode.READ_ONLY) public PackageURL getPurlCoordinates() { if (purlCoordinates == null) { return null; @@ -822,10 +823,13 @@ public void setComponentMetaInformation(ComponentMetaInformation componentMetaIn this.componentMetaInformation = componentMetaInformation; } + @JsonIgnore + @ApiModelProperty(hidden = true) public boolean isNew() { return isNew; } + @JsonIgnore public void setNew(final boolean aNew) { isNew = aNew; } @@ -838,30 +842,28 @@ public void setLastInheritedRiskScore(Double lastInheritedRiskScore) { this.lastInheritedRiskScore = lastInheritedRiskScore; } + @JsonIgnore + @ApiModelProperty(hidden = true) public String getBomRef() { return bomRef; } + @JsonIgnore public void setBomRef(String bomRef) { this.bomRef = bomRef; } + @JsonIgnore + @ApiModelProperty(hidden = true) public List getLicenseCandidates() { return licenseCandidates; } + @JsonIgnore public void setLicenseCandidates(final List licenseCandidates) { this.licenseCandidates = licenseCandidates; } - public int getUsedBy() { - return usedBy; - } - - public void setUsedBy(int usedBy) { - this.usedBy = usedBy; - } - public Set getDependencyGraph() { return dependencyGraph; } diff --git a/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java b/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java index 4fae0dbc9..7c81e1933 100644 --- a/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/AccessControlResource.java @@ -69,7 +69,8 @@ public class AccessControlResource extends AlpineResource { value = "Returns the projects assigned to the specified team", response = String.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects"), + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @PaginatedApi @ApiResponses(value = { @@ -99,7 +100,8 @@ public Response retrieveProjects (@ApiParam(value = "The UUID of the team to ret @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds an ACL mapping", - response = AclMappingRequest.class + response = AclMappingRequest.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -135,7 +137,8 @@ public Response addMapping(AclMappingRequest request) { @Path("/mapping/team/{teamUuid}/project/{projectUuid}") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Removes an ACL mapping" + value = "Removes an ACL mapping", + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java b/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java index 424dfdfd0..09d4222f8 100644 --- a/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/AnalysisResource.java @@ -72,7 +72,8 @@ public class AnalysisResource extends AlpineResource { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Retrieves an analysis trail", - response = Analysis.class + response = Analysis.class, + notes = "

Requires permission VIEW_VULNERABILITY

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -119,7 +120,8 @@ public Response retrieveAnalysis(@ApiParam(value = "The UUID of the project", fo @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Records an analysis decision", - response = Analysis.class + response = Analysis.class, + notes = "

Requires permission VULNERABILITY_ANALYSIS

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/BomResource.java b/src/main/java/org/dependencytrack/resources/v1/BomResource.java index 05582d2c1..94c23aabe 100644 --- a/src/main/java/org/dependencytrack/resources/v1/BomResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/BomResource.java @@ -51,7 +51,6 @@ import org.dependencytrack.resources.v1.vo.IsTokenBeingProcessedResponse; import org.glassfish.jersey.media.multipart.BodyPartEntity; import org.glassfish.jersey.media.multipart.FormDataBodyPart; -import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.media.multipart.FormDataParam; import javax.validation.Validator; @@ -98,7 +97,8 @@ public class BomResource extends AlpineResource { @Produces({CycloneDxMediaType.APPLICATION_CYCLONEDX_XML, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON, MediaType.APPLICATION_OCTET_STREAM}) @ApiOperation( value = "Returns dependency metadata for a project in CycloneDX format", - response = String.class + response = String.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -167,7 +167,8 @@ public Response exportProjectAsCycloneDx( @Produces(CycloneDxMediaType.APPLICATION_CYCLONEDX_XML) @ApiOperation( value = "Returns dependency metadata for a specific component in CycloneDX format", - response = String.class + response = String.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -213,14 +214,20 @@ public Response exportComponentAsCycloneDx( @ApiOperation( value = "Upload a supported bill of material format document", notes = """ - Expects CycloneDX and a valid project UUID. If a UUID is not specified, \ - then the projectName and projectVersion must be specified. \ - Optionally, if autoCreate is specified and 'true' and the project does not exist, \ - the project will be created. In this scenario, the principal making the request will \ - additionally need the PORTFOLIO_MANAGEMENT or PROJECT_CREATION_UPLOAD permission. - The BOM will be validated against the CycloneDX schema. If schema validation fails, \ - a response with problem details in RFC 9457 format will be returned. In this case, \ - the response's content type will be application/problem+json.""", +

+ Expects CycloneDX and a valid project UUID. If a UUID is not specified, + then the projectName and projectVersion must be specified. + Optionally, if autoCreate is specified and true and the project does not exist, + the project will be created. In this scenario, the principal making the request will + additionally need the PORTFOLIO_MANAGEMENT or + PROJECT_CREATION_UPLOAD permission. +

+

+ The BOM will be validated against the CycloneDX schema. If schema validation fails, + a response with problem details in RFC 9457 format will be returned. In this case, + the response's content type will be application/problem+json. +

+

Requires permission BOM_UPLOAD

""", response = BomUploadResponse.class, nickname = "UploadBomBase64Encoded" ) @@ -232,7 +239,7 @@ public Response exportComponentAsCycloneDx( @ApiResponse(code = 404, message = "The project could not be found") }) @PermissionRequired(Permissions.Constants.BOM_UPLOAD) - public Response uploadBom(BomSubmitRequest request) { + public Response uploadBom(@ApiParam(required = true) BomSubmitRequest request) { final Validator validator = getValidator(); if (request.getProject() != null) { // behavior in v3.0.0 failOnValidationError( @@ -293,14 +300,20 @@ public Response uploadBom(BomSubmitRequest request) { @ApiOperation( value = "Upload a supported bill of material format document", notes = """ - Expects CycloneDX and a valid project UUID. If a UUID is not specified, \ - then the projectName and projectVersion must be specified. \ - Optionally, if autoCreate is specified and 'true' and the project does not exist, \ - the project will be created. In this scenario, the principal making the request will \ - additionally need the PORTFOLIO_MANAGEMENT or PROJECT_CREATION_UPLOAD permission. - The BOM will be validated against the CycloneDX schema. If schema validation fails, \ - a response with problem details in RFC 9457 format will be returned. In this case, \ - the response's content type will be application/problem+json.""", +

+ Expects CycloneDX and a valid project UUID. If a UUID is not specified, + then the projectName and projectVersion must be specified. + Optionally, if autoCreate is specified and true and the project does not exist, + the project will be created. In this scenario, the principal making the request will + additionally need the PORTFOLIO_MANAGEMENT or + PROJECT_CREATION_UPLOAD permission. +

+

+ The BOM will be validated against the CycloneDX schema. If schema validation fails, + a response with problem details in RFC 9457 format will be returned. In this case, + the response's content type will be application/problem+json. +

+

Requires permission BOM_UPLOAD

""", response = BomUploadResponse.class, nickname = "UploadBom" ) @@ -319,9 +332,7 @@ public Response uploadBom(@FormDataParam("project") String projectUuid, @FormDataParam("parentName") String parentName, @FormDataParam("parentVersion") String parentVersion, @FormDataParam("parentUUID") String parentUUID, - final FormDataMultiPart multiPart) { - - final List artifactParts = multiPart.getFields("bom"); + @ApiParam(type = "string") @FormDataParam("bom") final List artifactParts) { if (projectUuid != null) { // behavior in v3.0.0 try (QueryManager qm = new QueryManager()) { final Project project = qm.getObjectByUuid(Project.class, projectUuid); @@ -366,7 +377,23 @@ public Response uploadBom(@FormDataParam("project") String projectUuid, @GET @Path("/token/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Determines if there are any tasks associated with the token that are being processed, or in the queue to be processed.", notes = "Deprecated. Use /v1/event/token/{uuid} instead.", response = IsTokenBeingProcessedResponse.class) + @ApiOperation( + value = "Determines if there are any tasks associated with the token that are being processed, or in the queue to be processed.", + notes = """ +

+ This endpoint is intended to be used in conjunction with uploading a supported BOM document. + Upon upload, a token will be returned. The token can then be queried using this endpoint to + determine if any tasks (such as vulnerability analysis) is being performed on the BOM: +

    +
  • A value of true indicates processing is occurring.
  • +
  • A value of false indicates that no processing is occurring for the specified token.
  • +
+ However, a value of false also does not confirm the token is valid, + only that no processing is associated with the specified token. +

+

Requires permission BOM_UPLOAD

+

Deprecated. Use /v1/event/token/{uuid} instead.

""", + response = IsTokenBeingProcessedResponse.class) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") }) diff --git a/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java b/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java index e451a7a55..9ebea2569 100644 --- a/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/ComponentResource.java @@ -98,7 +98,8 @@ public class ComponentResource extends AlpineResource { value = "Returns a list of all components for a given project", response = Component.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of components") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of components"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -134,7 +135,8 @@ public Response getAllComponents( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific component", - response = Component.class + response = Component.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -180,15 +182,18 @@ public Response getComponentByUuid( @Path("/integritymetadata") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Provides the published date and hashes of the requested version of component " + - "as received from configured repositories for integrity analysis", - response = IntegrityMetaComponent.class + value = """ + Provides the published date and hashes of the requested version of component, + as received from configured repositories for integrity analysis.""", + response = IntegrityMetaComponent.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 404, message = "The integrity meta information for the specified component cannot be found"), @ApiResponse(code = 400, message = "The package url being queried for is invalid") }) + @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO) public Response getIntegrityMetaComponent( @ApiParam(value = "The package url of the component", required = true) @QueryParam("purl") String purl) { @@ -216,14 +221,17 @@ public Response getIntegrityMetaComponent( @Path("/{uuid}/integritycheckstatus") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Provides the integrity check status of component with provided uuid based on the configured " + - "repository for integrity analysis", - response = IntegrityAnalysis.class + value = """ + Provides the integrity check status of component with provided UUID, + based on the configured repository for integrity analysis.""", + response = IntegrityAnalysis.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 404, message = "The integrity analysis information for the specified component cannot be found"), }) + @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO) public Response getIntegrityStatus( @ApiParam(value = "UUID of the component for which integrity status information is needed", format = "uuid", required = true) @PathParam("uuid") @ValidUuid String uuid) { @@ -245,7 +253,8 @@ public Response getIntegrityStatus( value = "Returns a list of components that have the specified component identity. This resource accepts coordinates (group, name, version) or purl, cpe, or swidTagId", responseContainer = "List", response = Component.class, - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of components") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of components"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -305,7 +314,8 @@ public Response getComponentByIdentity(@ApiParam(value = "The group of the compo value = "Returns a list of components that have the specified hash value", responseContainer = "List", response = Component.class, - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of components") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of components"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -328,7 +338,8 @@ public Response getComponentByHash( @ApiOperation( value = "Creates a new component", response = Component.class, - code = 201 + code = 201, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -446,7 +457,8 @@ public Response createComponent(@ApiParam(value = "The UUID of the project to cr @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a component", - response = Component.class + response = Component.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -565,7 +577,8 @@ public Response updateComponent(Component jsonComponent) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a component", - code = 204 + code = 204, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -593,7 +606,11 @@ public Response deleteComponent( @GET @Path("/internal/identify") @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Requests the identification of internal components in the portfolio", code = 204) + @ApiOperation( + value = "Requests the identification of internal components in the portfolio", + code = 204, + notes = "

Requires permission SYSTEM_CONFIGURATION

" + ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), }) @@ -609,7 +626,9 @@ public Response identifyInternalComponents() { @ApiOperation( value = "Returns the expanded dependency graph to every occurrence of a component", response = Component.class, - responseContainer = "Map") + responseContainer = "Map", + notes = "

Requires permission VIEW_PORTFOLIO

" + ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 403, message = "Access to the specified project is forbidden"), @@ -623,7 +642,7 @@ public Response getDependencyGraphForComponent( @PathParam("componentUuids") @ValidUuid String componentUuids) { try (QueryManager qm = new QueryManager()) { final Project project = qm.getObjectByUuid(Project.class, projectUuid); - if(project == null) { + if (project == null) { return Response.status(Response.Status.NOT_FOUND).entity("The UUID of the project could not be found.").build(); } @@ -633,9 +652,9 @@ public Response getDependencyGraphForComponent( final String[] componentUuidsSplit = componentUuids.split("\\|"); final List components = new ArrayList<>(); - for(String uuid : componentUuidsSplit) { + for (String uuid : componentUuidsSplit) { final Component component = qm.getObjectByUuid(Component.class, uuid); - if(component == null) { + if (component == null) { return Response.status(Response.Status.NOT_FOUND).entity("The UUID of the component could not be found.").build(); } components.add(component); diff --git a/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java b/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java index b31a70b8e..4038b4916 100644 --- a/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/ConfigPropertyResource.java @@ -54,7 +54,8 @@ public class ConfigPropertyResource extends AbstractConfigPropertyResource { @ApiOperation( value = "Returns a list of all ConfigProperties for the specified groupName", response = ConfigProperty.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -82,7 +83,8 @@ public Response getConfigProperties() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a config property", - response = ConfigProperty.class + response = ConfigProperty.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -109,7 +111,8 @@ public Response updateConfigProperty(ConfigProperty json) { @ApiOperation( value = "Updates an array of config properties", response = ConfigProperty.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java b/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java index b8516a01d..5b24e1f34 100644 --- a/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/DependencyGraphResource.java @@ -71,7 +71,8 @@ public class DependencyGraphResource extends AlpineResource { @ApiOperation( value = "Returns a list of specific components and services from project UUID", response = DependencyGraphResponse.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -110,7 +111,8 @@ public Response getComponentsAndServicesByProjectUuid(@ApiParam(value = "The UUI @ApiOperation( value = "Returns a list of specific components and services from component UUID", response = DependencyGraphResponse.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/EventResource.java b/src/main/java/org/dependencytrack/resources/v1/EventResource.java index 7f49d6f23..9b9fbdc21 100644 --- a/src/main/java/org/dependencytrack/resources/v1/EventResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/EventResource.java @@ -22,10 +22,10 @@ import alpine.server.resources.AlpineResource; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; import org.dependencytrack.model.validation.ValidUuid; import org.dependencytrack.resources.v1.vo.IsTokenBeingProcessedResponse; @@ -50,16 +50,25 @@ public class EventResource extends AlpineResource { @GET @Path("/token/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Determines if there are any tasks associated with the token that are being processed, or in the queue to be processed.", - notes = "This endpoint is intended to be used in conjunction with other API calls which return a token for asynchronous tasks. " + - "The token can then be queried using this endpoint to determine if the task is complete. " + - "A value of true indicates processing is occurring. A value of false indicates that no processing is " + - "occurring for the specified token. However, a value of false also does not confirm the token is valid, " + - "only that no processing is associated with the specified token.", response = IsTokenBeingProcessedResponse.class) + @ApiOperation( + value = "Determines if there are any tasks associated with the token that are being processed, or in the queue to be processed.", + response = IsTokenBeingProcessedResponse.class, + notes = """ +

+ This endpoint is intended to be used in conjunction with other API calls which return a token for asynchronous tasks. + The token can then be queried using this endpoint to determine if the task is complete: +

    +
  • A value of true indicates processing is occurring.
  • +
  • A value of false indicates that no processing is occurring for the specified token.
  • +
+ However, a value of false also does not confirm the token is valid, + only that no processing is associated with the specified token. +

""" + ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") }) - public Response isTokenBeingProcessed ( + public Response isTokenBeingProcessed( @ApiParam(value = "The UUID of the token to query", format = "uuid", required = true) @PathParam("uuid") @ValidUuid String uuid) { final boolean value = Event.isEventBeingProcessed(UUID.fromString(uuid)); diff --git a/src/main/java/org/dependencytrack/resources/v1/FindingResource.java b/src/main/java/org/dependencytrack/resources/v1/FindingResource.java index 46743fa0c..312b2b185 100644 --- a/src/main/java/org/dependencytrack/resources/v1/FindingResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/FindingResource.java @@ -32,6 +32,7 @@ import io.swagger.annotations.ResponseHeader; import org.dependencytrack.auth.Permissions; import org.dependencytrack.event.PortfolioRepositoryMetaAnalysisEvent; +import org.dependencytrack.event.PortfolioVulnerabilityAnalysisEvent; import org.dependencytrack.event.ProjectRepositoryMetaAnalysisEvent; import org.dependencytrack.event.ProjectVulnerabilityAnalysisEvent; import org.dependencytrack.integrations.FindingPackagingFormat; @@ -40,6 +41,7 @@ import org.dependencytrack.model.Vulnerability; import org.dependencytrack.model.validation.ValidUuid; import org.dependencytrack.persistence.QueryManager; +import org.dependencytrack.resources.v1.vo.BomUploadResponse; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -75,7 +77,8 @@ public class FindingResource extends AlpineResource { value = "Returns a list of all findings for a specific project", response = Finding.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of findings") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of findings"), + notes = "

Requires permission VIEW_VULNERABILITY

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -113,7 +116,8 @@ public Response getFindingsByProject(@ApiParam(value = "The UUID of the project" @Path("/project/{uuid}/export") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Returns the findings for the specified project as FPF" + value = "Returns the findings for the specified project as FPF", + notes = "

Requires permission VIEW_VULNERABILITY

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -143,7 +147,10 @@ public Response exportFindingsByProject(@ApiParam(value = "The UUID of the proje @POST @Path("/portfolio/analyze") - @ApiOperation(value = "Triggers Vulnerability Analysis for the entire portfolio") + @ApiOperation( + value = "Triggers Vulnerability Analysis for the entire portfolio", + notes = "

Requires permission SYSTEM_CONFIGURATION

" + ) @ApiResponses(value = { @ApiResponse(code = 304, message = "Analysis is already in progress"), @ApiResponse(code = 401, message = "Unauthorized") @@ -156,7 +163,7 @@ public Response analyzePortfolio() { return Response.status(Response.Status.NOT_MODIFIED).build(); } - Event.dispatch(new PortfolioRepositoryMetaAnalysisEvent()); + Event.dispatch(new PortfolioVulnerabilityAnalysisEvent()); return Response.ok().build(); } @@ -165,7 +172,8 @@ public Response analyzePortfolio() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Triggers Vulnerability Analysis on a specific project", - response = Project.class + response = BomUploadResponse.class, + notes = "

Requires permission VIEW_VULNERABILITY

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -204,7 +212,8 @@ public Response analyzeProject( value = "Returns a list of all findings", response = Finding.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of findings") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of findings"), + notes = "

Requires permission VIEW_VULNERABILITY

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -267,7 +276,8 @@ public Response getAllFindings(@ApiParam(value = "Show inactive projects") value = "Returns a list of all findings grouped by vulnerability", response = Finding.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of findings") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of findings"), + notes = "

Requires permission VIEW_VULNERABILITY

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") diff --git a/src/main/java/org/dependencytrack/resources/v1/OsvEcosytemResource.java b/src/main/java/org/dependencytrack/resources/v1/IntegrationResource.java similarity index 85% rename from src/main/java/org/dependencytrack/resources/v1/OsvEcosytemResource.java rename to src/main/java/org/dependencytrack/resources/v1/IntegrationResource.java index d39be32e7..6f4abe28e 100644 --- a/src/main/java/org/dependencytrack/resources/v1/OsvEcosytemResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/IntegrationResource.java @@ -36,16 +36,18 @@ import java.util.List; import java.util.stream.Collectors; -@Path("/v1/integration/osv/ecosystem") -@Api(value = "ecosystem", authorizations = @Authorization(value = "X-Api-Key")) -public class OsvEcosytemResource extends AlpineResource { +@Path("/v1/integration") +@Api(value = "integration", authorizations = @Authorization(value = "X-Api-Key")) +public class IntegrationResource extends AlpineResource { @GET + @Path("/osv/ecosystem") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a list of all ecosystems in OSV", response = String.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -58,12 +60,13 @@ public Response getAllEcosystems() { } @GET - @Path("/inactive") + @Path("/osv/ecosystem/inactive") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a list of available inactive ecosystems in OSV to be selected by user", response = String.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") diff --git a/src/main/java/org/dependencytrack/resources/v1/LdapResource.java b/src/main/java/org/dependencytrack/resources/v1/LdapResource.java index 7192b0e31..9d992f3cd 100644 --- a/src/main/java/org/dependencytrack/resources/v1/LdapResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/LdapResource.java @@ -73,13 +73,18 @@ public class LdapResource extends AlpineResource { response = String.class, responseContainer = "List", responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of ldap groups that match the specified search criteria"), - notes = "This API performs a pass-thru query to the configured LDAP server. Search criteria results are cached using default Alpine CacheManager policy" + notes = """ +

+ This API performs a pass-through query to the configured LDAP server. + Search criteria results are cached using default Alpine CacheManager policy. +

+

Requires permission ACCESS_MANAGEMENT

""" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") }) @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT) - public Response retrieveLdapGroups () { + public Response retrieveLdapGroups() { if (!LdapConnectionWrapper.LDAP_CONFIGURED) { return Response.ok().build(); } @@ -117,15 +122,16 @@ public Response retrieveLdapGroups () { @ApiOperation( value = "Returns the DNs of all groups mapped to the specified team", response = String.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 404, message = "The UUID of the team could not be found"), }) @PermissionRequired(Permissions.Constants.ACCESS_MANAGEMENT) - public Response retrieveLdapGroups (@ApiParam(value = "The UUID of the team to retrieve mappings for", format = "uuid", required = true) - @PathParam("uuid") @ValidUuid String uuid) { + public Response retrieveLdapGroups(@ApiParam(value = "The UUID of the team to retrieve mappings for", format = "uuid", required = true) + @PathParam("uuid") @ValidUuid String uuid) { try (QueryManager qm = new QueryManager()) { final Team team = qm.getObjectByUuid(Team.class, uuid); if (team != null) { @@ -142,7 +148,8 @@ public Response retrieveLdapGroups (@ApiParam(value = "The UUID of the team to r @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds a mapping", - response = MappedLdapGroup.class + response = MappedLdapGroup.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -176,7 +183,8 @@ public Response addMapping(MappedLdapGroupRequest request) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes a mapping", - response = MappedLdapGroup.class + response = MappedLdapGroup.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java b/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java index 17fb8d78f..563fce13b 100644 --- a/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/LicenseGroupResource.java @@ -65,7 +65,8 @@ public class LicenseGroupResource extends AlpineResource { value = "Returns a list of all license groups", response = LicenseGroup.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of license groups") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of license groups"), + notes = "

Requires permission POLICY_MANAGEMENT

" ) @PaginatedApi @ApiResponses(value = { @@ -84,7 +85,8 @@ public Response getLicenseGroups() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific license group", - response = License.class + response = License.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -110,7 +112,8 @@ public Response getLicenseGroup( @ApiOperation( value = "Creates a new license group", response = LicenseGroup.class, - code = 201 + code = 201, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -139,7 +142,8 @@ public Response createLicenseGroup(LicenseGroup jsonLicenseGroup) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a license group", - response = LicenseGroup.class + response = LicenseGroup.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -169,7 +173,8 @@ public Response updateLicenseGroup(LicenseGroup jsonLicenseGroup) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a license group", - code = 204 + code = 204, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -196,7 +201,8 @@ public Response deleteLicenseGroup( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds the license to the specified license group.", - response = LicenseGroup.class + response = LicenseGroup.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The license group already has the specified license assigned"), @@ -235,7 +241,8 @@ public Response addLicenseToLicenseGroup( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes the license from the license group.", - response = LicenseGroup.class + response = LicenseGroup.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The license is not a member with the license group"), diff --git a/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java b/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java index 28a76431e..765488a4b 100644 --- a/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/LicenseResource.java @@ -122,7 +122,8 @@ public Response getLicense( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Creates a new custom license", - response = License.class + response = License.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -137,7 +138,7 @@ public Response createLicense(License jsonLicense) { ); try (QueryManager qm = new QueryManager()) { License license = qm.getLicense(jsonLicense.getLicenseId()); - if (license == null){ + if (license == null) { license = qm.createCustomLicense(jsonLicense, true); LOGGER.info("License " + license.getName() + " created by " + super.getPrincipal().getName()); return Response.status(Response.Status.CREATED).entity(license).build(); @@ -152,7 +153,8 @@ public Response createLicense(License jsonLicense) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a custom license", - code = 204 + code = 204, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java b/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java index 1df16154e..4c342772a 100644 --- a/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/MetricsResource.java @@ -67,7 +67,8 @@ public class MetricsResource extends AlpineResource { @ApiOperation( value = "Returns the sum of all vulnerabilities in the database by year and month", response = VulnerabilityMetrics.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -85,7 +86,8 @@ public Response getVulnerabilityMetrics() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns current metrics for the entire portfolio", - response = PortfolioMetrics.class + response = PortfolioMetrics.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -103,7 +105,9 @@ public Response getPortfolioCurrentMetrics() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns historical metrics for the entire portfolio from a specific date", - notes = "Date format must be YYYYMMDD", + notes = """ +

Date format must be YYYYMMDD

+

Requires permission VIEW_PORTFOLIO

""", response = PortfolioMetrics.class, responseContainer = "List" ) @@ -131,7 +135,8 @@ public Response getPortfolioMetricsSince( @ApiOperation( value = "Returns X days of historical metrics for the entire portfolio", response = PortfolioMetrics.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -153,7 +158,8 @@ public Response getPortfolioMetricsXDays( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Requests a refresh of the portfolio metrics", - response = PortfolioMetrics.class + response = PortfolioMetrics.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -169,7 +175,8 @@ public Response RefreshPortfolioMetrics() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns current metrics for a specific project", - response = ProjectMetrics.class + response = ProjectMetrics.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -200,7 +207,9 @@ public Response getProjectCurrentMetrics( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns historical metrics for a specific project from a specific date", - notes = "Date format must be YYYYMMDD", + notes = """ +

Date format must be YYYYMMDD

+

Requires permission VIEW_PORTFOLIO

""", response = ProjectMetrics.class, responseContainer = "List" ) @@ -226,7 +235,8 @@ public Response getProjectMetricsSince( @ApiOperation( value = "Returns X days of historical metrics for a specific project", response = ProjectMetrics.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -248,7 +258,8 @@ public Response getProjectMetricsXDays( @Path("/project/{uuid}/refresh") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Requests a refresh of a specific projects metrics" + value = "Requests a refresh of a specific projects metrics", + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -279,7 +290,8 @@ public Response RefreshProjectMetrics( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns current metrics for a specific component", - response = DependencyMetrics.class + response = DependencyMetrics.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -310,7 +322,9 @@ public Response getComponentCurrentMetrics( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns historical metrics for a specific component from a specific date", - notes = "Date format must be YYYYMMDD", + notes = """ +

Date format must be YYYYMMDD

+

Requires permission VIEW_PORTFOLIO

""", response = DependencyMetrics.class, responseContainer = "List" ) @@ -339,7 +353,8 @@ public Response getComponentMetricsSince( @ApiOperation( value = "Returns X days of historical metrics for a specific component", response = DependencyMetrics.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -361,7 +376,8 @@ public Response getComponentMetricsXDays( @Path("/component/{uuid}/refresh") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Requests a refresh of a specific components metrics" + value = "Requests a refresh of a specific components metrics", + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java b/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java index 0a7522b2c..7cf337388 100644 --- a/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/NotificationPublisherResource.java @@ -59,7 +59,7 @@ * @since 3.2.0 */ @Path("/v1/notification/publisher") -@Api(authorizations = @Authorization(value = "X-Api-Key")) +@Api(value = "notification", authorizations = @Authorization(value = "X-Api-Key")) public class NotificationPublisherResource extends AlpineResource { private static final Logger LOGGER = Logger.getLogger(NotificationPublisherResource.class); @@ -69,7 +69,8 @@ public class NotificationPublisherResource extends AlpineResource { @ApiOperation( value = "Returns a list of all notification publishers", response = NotificationPublisher.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -88,7 +89,8 @@ public Response getAllNotificationPublishers() { @ApiOperation( value = "Creates a new notification publisher", response = NotificationPublisher.class, - code = 201 + code = 201, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid notification class or trying to modify a default publisher"), @@ -124,7 +126,7 @@ public Response createNotificationPublisher(NotificationPublisher jsonNotificati ); return Response.status(Response.Status.CREATED).entity(notificationPublisherCreated).build(); } else { - return Response.status(Response.Status.BAD_REQUEST).entity("The publisher class "+jsonNotificationPublisher.getPublisherClass()+" is not valid.").build(); + return Response.status(Response.Status.BAD_REQUEST).entity("The publisher class " + jsonNotificationPublisher.getPublisherClass() + " is not valid.").build(); } } } @@ -134,7 +136,8 @@ public Response createNotificationPublisher(NotificationPublisher jsonNotificati @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a notification publisher", - response = NotificationRule.class + response = NotificationRule.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid notification class or trying to modify a default publisher"), @@ -157,14 +160,14 @@ public Response updateNotificationPublisher(NotificationPublisher jsonNotificati try (QueryManager qm = new QueryManager()) { NotificationPublisher existingPublisher = qm.getObjectByUuid(NotificationPublisher.class, jsonNotificationPublisher.getUuid()); if (existingPublisher != null) { - if(existingPublisher.isDefaultPublisher()) { + if (existingPublisher.isDefaultPublisher()) { return Response.status(Response.Status.BAD_REQUEST).entity("The modification of a default publisher is forbidden").build(); } - if(!jsonNotificationPublisher.getName().equals(existingPublisher.getName())) { + if (!jsonNotificationPublisher.getName().equals(existingPublisher.getName())) { NotificationPublisher existingNotificationPublisherWithModifiedName = qm.getNotificationPublisher(jsonNotificationPublisher.getName()); - if(existingNotificationPublisherWithModifiedName != null) { - return Response.status(Response.Status.CONFLICT).entity("An existing publisher with the name '"+existingNotificationPublisherWithModifiedName.getName()+"' already exist").build(); + if (existingNotificationPublisherWithModifiedName != null) { + return Response.status(Response.Status.CONFLICT).entity("An existing publisher with the name '" + existingNotificationPublisherWithModifiedName.getName() + "' already exist").build(); } } existingPublisher.setName(jsonNotificationPublisher.getName()); @@ -174,7 +177,7 @@ public Response updateNotificationPublisher(NotificationPublisher jsonNotificati clazz.name().equalsIgnoreCase(jsonNotificationPublisher.getPublisherClass()))) { existingPublisher.setPublisherClass(jsonNotificationPublisher.getPublisherClass()); } else { - return Response.status(Response.Status.BAD_REQUEST).entity("The publisher class "+jsonNotificationPublisher.getPublisherClass()+" is not valid.").build(); + return Response.status(Response.Status.BAD_REQUEST).entity("The publisher class " + jsonNotificationPublisher.getPublisherClass() + " is not valid.").build(); } existingPublisher.setTemplate(jsonNotificationPublisher.getTemplate()); existingPublisher.setTemplateMimeType(jsonNotificationPublisher.getTemplateMimeType()); @@ -193,7 +196,8 @@ public Response updateNotificationPublisher(NotificationPublisher jsonNotificati @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a notification publisher and all related notification rules", - code = 204 + code = 204, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Deleting a default notification publisher is forbidden"), @@ -206,7 +210,7 @@ public Response deleteNotificationPublisher(@ApiParam(value = "The UUID of the n try (QueryManager qm = new QueryManager()) { final NotificationPublisher notificationPublisher = qm.getObjectByUuid(NotificationPublisher.class, notificationPublisherUuid); if (notificationPublisher != null) { - if(notificationPublisher.isDefaultPublisher()) { + if (notificationPublisher.isDefaultPublisher()) { return Response.status(Response.Status.BAD_REQUEST).entity("Deleting a default notification publisher is forbidden.").build(); } else { qm.deleteNotificationPublisher(notificationPublisher); @@ -223,7 +227,8 @@ public Response deleteNotificationPublisher(@ApiParam(value = "The UUID of the n @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Restore the default notification publisher templates using the ones in the solution classpath" + value = "Restore the default notification publisher templates using the ones in the solution classpath", + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") diff --git a/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java b/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java index 40ff969d6..2387c7437 100644 --- a/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/NotificationRuleResource.java @@ -61,7 +61,7 @@ * @since 3.2.0 */ @Path("/v1/notification/rule") -@Api(authorizations = @Authorization(value = "X-Api-Key")) +@Api(value = "notification", authorizations = @Authorization(value = "X-Api-Key")) public class NotificationRuleResource extends AlpineResource { @GET @@ -70,7 +70,8 @@ public class NotificationRuleResource extends AlpineResource { value = "Returns a list of all notification rules", response = NotificationRule.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of notification rules") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of notification rules"), + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @PaginatedApi @ApiResponses(value = { @@ -90,7 +91,8 @@ public Response getAllNotificationRules() { @ApiOperation( value = "Creates a new notification rule", response = NotificationRule.class, - code = 201 + code = 201, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -126,7 +128,8 @@ public Response createNotificationRule(NotificationRule jsonRule) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a notification rule", - response = NotificationRule.class + response = NotificationRule.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -157,7 +160,8 @@ public Response updateNotificationRule(NotificationRule jsonRule) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a notification rule", - code = 204 + code = 204, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -182,7 +186,8 @@ public Response deleteNotificationRule(NotificationRule jsonRule) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds a project to a notification rule", - response = NotificationRule.class + response = NotificationRule.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The rule already has the specified project assigned"), @@ -223,7 +228,8 @@ public Response addProjectToRule( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes a project from a notification rule", - response = NotificationRule.class + response = NotificationRule.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The rule does not have the specified project assigned"), @@ -264,7 +270,8 @@ public Response removeProjectFromRule( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds a team to a notification rule", - response = NotificationRule.class + response = NotificationRule.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The rule already has the specified team assigned"), @@ -305,7 +312,8 @@ public Response addTeamToRule( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes a team from a notification rule", - response = NotificationRule.class + response = NotificationRule.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The rule does not have the specified team assigned"), diff --git a/src/main/java/org/dependencytrack/resources/v1/OidcResource.java b/src/main/java/org/dependencytrack/resources/v1/OidcResource.java index 5c37a2a6c..9a6f9170f 100644 --- a/src/main/java/org/dependencytrack/resources/v1/OidcResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/OidcResource.java @@ -81,7 +81,8 @@ public Response isAvailable() { @ApiOperation( value = "Returns a list of all groups", response = OidcGroup.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -101,7 +102,8 @@ public Response retrieveGroups() { @ApiOperation( value = "Creates group", response = OidcGroup.class, - code = 201 + code = 201, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -130,7 +132,8 @@ public Response createGroup(final OidcGroup jsonGroup) { @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates group", - response = OidcGroup.class + response = OidcGroup.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -161,7 +164,8 @@ public Response updateGroup(final OidcGroup jsonGroup) { @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a group", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -189,7 +193,8 @@ public Response deleteGroup(@ApiParam(value = "The UUID of the group to delete", @ApiOperation( value = "Returns a list of teams associated with the specified group", response = Team.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -217,7 +222,8 @@ public Response retrieveTeamsMappedToGroup(@ApiParam(value = "The UUID of the ma @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds a mapping", - response = MappedOidcGroup.class + response = MappedOidcGroup.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -258,7 +264,8 @@ public Response addMapping(final MappedOidcGroupRequest request) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a mapping", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -284,7 +291,8 @@ public Response deleteMappingByUuid(@ApiParam(value = "The UUID of the mapping t @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a mapping", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java b/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java index 3196bff7a..02e2cc168 100644 --- a/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/PermissionResource.java @@ -63,7 +63,8 @@ public class PermissionResource extends AlpineResource { @ApiOperation( value = "Returns a list of all permissions", response = alpine.model.Permission.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -82,7 +83,8 @@ public Response getAllPermissions() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds the permission to the specified username.", - response = UserPrincipal.class + response = UserPrincipal.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The user already has the specified permission assigned"), @@ -122,7 +124,8 @@ public Response addPermissionToUser( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes the permission from the user.", - response = UserPrincipal.class + response = UserPrincipal.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The user already has the specified permission assigned"), @@ -162,8 +165,8 @@ public Response removePermissionFromUser( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds the permission to the specified team.", - notes = "Requires 'manage users' permission.", - response = Team.class + response = Team.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The team already has the specified permission assigned"), @@ -203,7 +206,8 @@ public Response addPermissionToTeam( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes the permission from the team.", - response = Team.class + response = Team.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The team already has the specified permission assigned"), diff --git a/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java b/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java index f5f8af6c1..9bfdf2036 100644 --- a/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/PolicyConditionResource.java @@ -70,7 +70,8 @@ public class PolicyConditionResource extends AlpineResource { @ApiOperation( value = "Creates a new policy condition", response = PolicyCondition.class, - code = 201 + code = 201, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -106,7 +107,7 @@ public Response createPolicyCondition( @ApiOperation( value = "Updates a policy condition", response = PolicyCondition.class, - code = 200 + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -136,7 +137,8 @@ public Response updatePolicyCondition(PolicyCondition jsonPolicyCondition) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a policy condition", - code = 204 + code = 204, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java b/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java index 09144cd09..9daf1f91e 100644 --- a/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/PolicyResource.java @@ -66,7 +66,8 @@ public class PolicyResource extends AlpineResource { value = "Returns a list of all policies", response = Policy.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policies") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policies"), + notes = "

Requires permission POLICY_MANAGEMENT

" ) @PaginatedApi @ApiResponses(value = { @@ -85,7 +86,8 @@ public Response getPolicies() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific policy", - response = Policy.class + response = Policy.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -111,7 +113,8 @@ public Response getPolicy( @ApiOperation( value = "Creates a new policy", response = Policy.class, - code = 201 + code = 201, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -150,7 +153,8 @@ public Response createPolicy(Policy jsonPolicy) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a policy", - response = Policy.class + response = Policy.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -183,7 +187,8 @@ public Response updatePolicy(Policy jsonPolicy) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a policy", - code = 204 + code = 204, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -210,7 +215,8 @@ public Response deletePolicy( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds a project to a policy", - response = Policy.class + response = Policy.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The policy already has the specified project assigned"), @@ -248,7 +254,8 @@ public Response addProjectToPolicy( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes a project from a policy", - response = Policy.class + response = Policy.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The policy does not have the specified project assigned"), @@ -286,7 +293,8 @@ public Response removeProjectFromPolicy( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds a tag to a policy", - response = Policy.class + response = Policy.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The policy already has the specified tag assigned"), @@ -325,7 +333,8 @@ public Response addTagToPolicy( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes a tag from a policy", - response = Policy.class + response = Policy.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The policy does not have the specified tag assigned"), diff --git a/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java b/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java index c840aaca5..0f2c89b85 100644 --- a/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/PolicyViolationResource.java @@ -63,7 +63,8 @@ public class PolicyViolationResource extends AlpineResource { value = "Returns a list of all policy violations for the entire portfolio", response = PolicyViolation.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policy violations") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policy violations"), + notes = "

Requires permission VIEW_POLICY_VIOLATION

" ) @PaginatedApi @ApiResponses(value = { @@ -87,7 +88,8 @@ public Response getViolations(@ApiParam(value = "Optionally includes suppressed value = "Returns a list of all policy violations for a specific project", response = PolicyViolation.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policy violations") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policy violations"), + notes = "

Requires permission VIEW_POLICY_VIOLATION

" ) @PaginatedApi @ApiResponses(value = { @@ -124,7 +126,8 @@ public Response getViolationsByProject(@ApiParam(value = "The UUID of the projec value = "Returns a list of all policy violations for a specific component", response = PolicyViolation.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policy violations") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of policy violations"), + notes = "

Requires permission VIEW_POLICY_VIOLATION

" ) @PaginatedApi @ApiResponses(value = { diff --git a/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java b/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java index 2691df161..8c6c386e4 100644 --- a/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/ProjectPropertyResource.java @@ -60,7 +60,8 @@ public class ProjectPropertyResource extends AbstractConfigPropertyResource { @ApiOperation( value = "Returns a list of all ProjectProperties for the specified project", response = ProjectProperty.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -80,7 +81,7 @@ public Response getProperties( // values are replaced by the placeholder, they are not erroneously persisted to the database. qm.getPersistenceManager().detachCopyAll(properties); qm.close(); - for (final ProjectProperty property: properties) { + for (final ProjectProperty property : properties) { // Replace the value of encrypted strings with the pre-defined placeholder if (ProjectProperty.PropertyType.ENCRYPTEDSTRING == property.getPropertyType()) { property.setPropertyValue(ENCRYPTED_PLACEHOLDER); @@ -102,7 +103,8 @@ public Response getProperties( @ApiOperation( value = "Creates a new project property", response = ProjectProperty.class, - code = 201 + code = 201, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -158,7 +160,8 @@ public Response createProperty( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a project property", - response = ProjectProperty.class + response = ProjectProperty.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -200,7 +203,8 @@ public Response updateProperty( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a config property", - response = ProjectProperty.class + response = ProjectProperty.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java b/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java index a1875c982..935d406d9 100644 --- a/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/ProjectResource.java @@ -90,7 +90,8 @@ public class ProjectResource extends AlpineResource { value = "Returns a list of all projects", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -114,7 +115,8 @@ public Response getProjects(@ApiParam(value = "The optional name of the project } } - final PaginatedResult result = (name != null) ? qm.getProjects(name, excludeInactive, onlyRoot, notAssignedToTeam) : qm.getProjects(true, excludeInactive, onlyRoot, notAssignedToTeam); return Response.ok(result.getObjects()).header(TOTAL_COUNT_HEADER, result.getTotal()).build(); + final PaginatedResult result = (name != null) ? qm.getProjects(name, excludeInactive, onlyRoot, notAssignedToTeam) : qm.getProjects(true, excludeInactive, onlyRoot, notAssignedToTeam); + return Response.ok(result.getObjects()).header(TOTAL_COUNT_HEADER, result.getTotal()).build(); } } @@ -123,7 +125,8 @@ public Response getProjects(@ApiParam(value = "The optional name of the project @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific project", - response = Project.class + response = Project.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -151,7 +154,12 @@ public Response getProject( @GET @Path("/lookup") @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Returns a specific project by its name and version", response = Project.class, nickname = "getProjectByNameAndVersion") + @ApiOperation( + value = "Returns a specific project by its name and version", + response = Project.class, + nickname = "getProjectByNameAndVersion", + notes = "

Requires permission VIEW_PORTFOLIO

" + ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 403, message = "Access to the specified project is forbidden"), @@ -184,7 +192,8 @@ public Response getProject( value = "Returns a list of all projects by tag", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects with the tag") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects with the tag"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -212,7 +221,8 @@ public Response getProjectsByTag( value = "Returns a list of all projects by classifier", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects of the specified classifier") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects of the specified classifier"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -240,13 +250,19 @@ public Response getProjectsByClassifier( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Creates a new project", - notes = "If a parent project exists, the UUID of the parent project is required ", + notes = """ +

If a parent project exists, parent.uuid is required

+

Requires permission PORTFOLIO_MANAGEMENT

""", response = Project.class, code = 201 ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), - @ApiResponse(code = 409, message = "- An inactive Parent cannot be selected as parent\n- A project with the specified name already exists"), + @ApiResponse(code = 409, message = """ +
    +
  • An inactive Parent cannot be selected as parent, or
  • +
  • A project with the specified name already exists
  • +
"""), }) @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT) public Response createProject(Project jsonProject) { @@ -297,12 +313,19 @@ public Response createProject(Project jsonProject) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a project", - response = Project.class + response = Project.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 404, message = "The UUID of the project could not be found"), - @ApiResponse(code = 409, message = "- An inactive Parent cannot be selected as parent\n- Project cannot be set to inactive if active children are present\n- A project with the specified name already exists\n- A project cannot select itself as a parent") + @ApiResponse(code = 409, message = """ +
    +
  • An inactive Parent cannot be selected as parent, or
  • +
  • Project cannot be set to inactive if active children are present, or
  • +
  • A project with the specified name already exists, or
  • +
  • A project cannot select itself as a parent
  • +
""") }) @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT) public Response updateProject(Project jsonProject) { @@ -360,12 +383,19 @@ public Response updateProject(Project jsonProject) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Partially updates a project", - response = Project.class + response = Project.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 404, message = "The UUID of the project could not be found"), - @ApiResponse(code = 409, message = "- An inactive Parent cannot be selected as parent\n- Project cannot be set to inactive if active children are present\n- A project with the specified name already exists\n- A project cannot select itself as a parent") + @ApiResponse(code = 409, message = """ +
    +
  • An inactive Parent cannot be selected as parent, or
  • +
  • Project cannot be set to inactive if active children are present, or
  • +
  • A project with the specified name already exists, or
  • +
  • A project cannot select itself as a parent
  • +
""") }) @PermissionRequired(Permissions.Constants.PORTFOLIO_MANAGEMENT) public Response patchProject( @@ -489,7 +519,8 @@ private boolean setIfDifferent(final Project source, final Project target, f @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a project", - code = 204 + code = 204, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -525,7 +556,8 @@ public Response deleteProject( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Clones a project", - response = Project.class + response = Project.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -588,7 +620,8 @@ public Response cloneProject(CloneProjectRequest jsonRequest) { value = "Returns a list of all children for a project", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -623,7 +656,8 @@ public Response getChildrenProjects(@ApiParam(value = "The UUID of the project t value = "Returns a list of all children for a project by classifier", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -662,7 +696,8 @@ public Response getChildrenProjectsByClassifier( value = "Returns a list of all children for a project by tag", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -701,7 +736,8 @@ public Response getChildrenProjectsByTag( value = "Returns a list of all projects without the descendants of the selected project", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { diff --git a/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java b/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java index 74b8aa6ad..ed09143a8 100644 --- a/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/RepositoryResource.java @@ -71,7 +71,8 @@ public class RepositoryResource extends AlpineResource { value = "Returns a list of all repositories", response = Repository.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of repositories") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of repositories"), + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @PaginatedApi @ApiResponses(value = { @@ -92,7 +93,8 @@ public Response getRepositories() { value = "Returns repositories that support the specific type", response = Repository.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of repositories") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of repositories"), + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @PaginatedApi @ApiResponses(value = { @@ -151,7 +153,8 @@ public Response getRepositoryMetaComponent( @ApiOperation( value = "Creates a new repository", response = Repository.class, - code = 201 + code = 201, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -192,7 +195,8 @@ public Response createRepository(Repository jsonRepository) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a repository", - response = Repository.class + response = Repository.class, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -236,7 +240,8 @@ public Response updateRepository(Repository jsonRepository) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a repository", - code = 204 + code = 204, + notes = "

Requires permission SYSTEM_CONFIGURATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java b/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java index 3a27e6cf0..998f0fe6c 100644 --- a/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/ServiceResource.java @@ -65,7 +65,8 @@ public class ServiceResource extends AlpineResource { value = "Returns a list of all services for a given project", response = ServiceComponent.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of services") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of services"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -96,7 +97,8 @@ public Response getAllServices(@ApiParam(value = "The UUID of the project", form @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific service", - response = ServiceComponent.class + response = ServiceComponent.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -130,7 +132,8 @@ public Response getServiceByUuid( @ApiOperation( value = "Creates a new service", response = ServiceComponent.class, - code = 201 + code = 201, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -157,7 +160,7 @@ public Response createService(@ApiParam(value = "The UUID of the project", forma if (project == null) { return Response.status(Response.Status.NOT_FOUND).entity("The project could not be found.").build(); } - if (! qm.hasAccess(super.getPrincipal(), project)) { + if (!qm.hasAccess(super.getPrincipal(), project)) { return Response.status(Response.Status.FORBIDDEN).entity("Access to the specified project is forbidden").build(); } ServiceComponent service = new ServiceComponent(); @@ -182,7 +185,8 @@ public Response createService(@ApiParam(value = "The UUID of the project", forma @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a service", - response = ServiceComponent.class + response = ServiceComponent.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -201,7 +205,7 @@ public Response updateService(ServiceComponent jsonService) { try (QueryManager qm = new QueryManager()) { ServiceComponent service = qm.getObjectByUuid(ServiceComponent.class, jsonService.getUuid()); if (service != null) { - if (! qm.hasAccess(super.getPrincipal(), service.getProject())) { + if (!qm.hasAccess(super.getPrincipal(), service.getProject())) { return Response.status(Response.Status.FORBIDDEN).entity("Access to the specified service is forbidden").build(); } // Name cannot be empty or null - prevent it @@ -232,7 +236,8 @@ public Response updateService(ServiceComponent jsonService) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a service", - code = 204 + code = 204, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -246,7 +251,7 @@ public Response deleteService( try (QueryManager qm = new QueryManager()) { final ServiceComponent service = qm.getObjectByUuid(ServiceComponent.class, uuid, ServiceComponent.FetchGroup.ALL.name()); if (service != null) { - if (! qm.hasAccess(super.getPrincipal(), service.getProject())) { + if (!qm.hasAccess(super.getPrincipal(), service.getProject())) { return Response.status(Response.Status.FORBIDDEN).entity("Access to the specified service is forbidden").build(); } qm.recursivelyDelete(service, false); diff --git a/src/main/java/org/dependencytrack/resources/v1/TagResource.java b/src/main/java/org/dependencytrack/resources/v1/TagResource.java index eedd7b93f..2512c732e 100644 --- a/src/main/java/org/dependencytrack/resources/v1/TagResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/TagResource.java @@ -51,14 +51,15 @@ public class TagResource extends AlpineResource { value = "Returns a list of all tags associated with a given policy", response = Tag.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of tags") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of tags"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") }) @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO) public Response getTags(@ApiParam(value = "The UUID of the policy", format = "uuid", required = true) - @PathParam("policyUuid") @ValidUuid String policyUuid){ + @PathParam("policyUuid") @ValidUuid String policyUuid) { try (QueryManager qm = new QueryManager(getAlpineRequest())) { final PaginatedResult result = qm.getTags(policyUuid); return Response.ok(result.getObjects()).header(TOTAL_COUNT_HEADER, result.getTotal()).build(); diff --git a/src/main/java/org/dependencytrack/resources/v1/TeamResource.java b/src/main/java/org/dependencytrack/resources/v1/TeamResource.java index 374753568..9ac8c29db 100644 --- a/src/main/java/org/dependencytrack/resources/v1/TeamResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/TeamResource.java @@ -70,7 +70,8 @@ public class TeamResource extends AlpineResource { value = "Returns a list of all teams", response = Team.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of teams") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of teams"), + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -89,7 +90,8 @@ public Response getTeams() { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific team", - response = Team.class + response = Team.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -115,7 +117,8 @@ public Response getTeam( @ApiOperation( value = "Creates a new team along with an associated API key", response = Team.class, - code = 201 + code = 201, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -141,7 +144,8 @@ public Response createTeam(Team jsonTeam) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a team's fields including", - response = Team.class + response = Team.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -172,7 +176,8 @@ public Response updateTeam(Team jsonTeam) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a team", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -199,7 +204,8 @@ public Response deleteTeam(Team jsonTeam) { @ApiOperation( value = "Generates an API key and returns its value", response = ApiKey.class, - code = 201 + code = 201, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -225,7 +231,8 @@ public Response generateApiKey( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Regenerates an API key by removing the specified key, generating a new one and returning its value", - response = ApiKey.class + response = ApiKey.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -250,7 +257,11 @@ public Response regenerateApiKey( @Path("/key/{apikey}/comment") @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Updates an API key's comment", response = ApiKey.class) + @ApiOperation( + value = "Updates an API key's comment", + response = ApiKey.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" + ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 404, message = "The API key could not be found") @@ -279,7 +290,8 @@ public Response updateApiKeyComment(@PathParam("apikey") final String apikey, @Path("/key/{apikey}") @ApiOperation( value = "Deletes the specified API key", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -316,7 +328,7 @@ public Response getSelf() { if (Config.getInstance().getPropertyAsBoolean(Config.AlpineKey.ENFORCE_AUTHENTICATION)) { try (var qm = new QueryManager()) { if (isApiKey()) { - final var apiKey = qm.getApiKey(((ApiKey)getPrincipal()).getKey()); + final var apiKey = qm.getApiKey(((ApiKey) getPrincipal()).getKey()); final var team = apiKey.getTeams().stream().findFirst(); if (team.isPresent()) { return Response.ok(new TeamSelfResponse(team.get())).build(); diff --git a/src/main/java/org/dependencytrack/resources/v1/UserResource.java b/src/main/java/org/dependencytrack/resources/v1/UserResource.java index 40c4c8126..df8e39487 100644 --- a/src/main/java/org/dependencytrack/resources/v1/UserResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/UserResource.java @@ -232,7 +232,8 @@ public Response forceChangePassword(@FormParam("username") String username, @For value = "Returns a list of all managed users", response = ManagedUser.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of managed users") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of managed users"), + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -253,7 +254,8 @@ public Response getManagedUsers() { value = "Returns a list of all LDAP users", response = LdapUser.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of LDAP users") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of LDAP users"), + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -277,7 +279,8 @@ public Response getLdapUsers() { value = "Returns a list of all OIDC users", response = OidcUser.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of OIDC users") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of OIDC users"), + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -376,7 +379,8 @@ public Response updateSelf(ManagedUser jsonUser) { @ApiOperation( value = "Creates a new user that references an existing LDAP object.", response = LdapUser.class, - code = 201 + code = 201, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Username cannot be null or blank."), @@ -407,7 +411,8 @@ public Response createLdapUser(LdapUser jsonUser) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a user.", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -436,7 +441,8 @@ public Response deleteLdapUser(LdapUser jsonUser) { @ApiOperation( value = "Creates a new user.", response = ManagedUser.class, - code = 201 + code = 201, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Missing required field"), @@ -483,7 +489,8 @@ public Response createManagedUser(ManagedUser jsonUser) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates a managed user.", - response = ManagedUser.class + response = ManagedUser.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Missing required field"), @@ -525,7 +532,8 @@ public Response updateManagedUser(ManagedUser jsonUser) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a user.", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -554,7 +562,8 @@ public Response deleteManagedUser(ManagedUser jsonUser) { @ApiOperation( value = "Creates a new user that references an existing OpenID Connect user.", response = OidcUser.class, - code = 201 + code = 201, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Username cannot be null or blank."), @@ -585,7 +594,8 @@ public Response createOidcUser(final OidcUser jsonUser) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes an OpenID Connect user.", - code = 204 + code = 204, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -613,7 +623,8 @@ public Response deleteOidcUser(final OidcUser jsonUser) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Adds the username to the specified team.", - response = UserPrincipal.class + response = UserPrincipal.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The user is already a member of the specified team"), @@ -625,7 +636,7 @@ public Response addTeamToUser( @ApiParam(value = "A valid username", required = true) @PathParam("username") String username, @ApiParam(value = "The UUID of the team to associate username with", required = true) - IdentifiableObject identifiableObject) { + IdentifiableObject identifiableObject) { try (QueryManager qm = new QueryManager()) { final Team team = qm.getObjectByUuid(Team.class, identifiableObject.getUuid()); if (team == null) { @@ -652,7 +663,8 @@ public Response addTeamToUser( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Removes the username from the specified team.", - response = UserPrincipal.class + response = UserPrincipal.class, + notes = "

Requires permission ACCESS_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 304, message = "The user was not a member of the specified team"), @@ -664,7 +676,7 @@ public Response removeTeamFromUser( @ApiParam(value = "A valid username", required = true) @PathParam("username") String username, @ApiParam(value = "The UUID of the team to un-associate username from", required = true) - IdentifiableObject identifiableObject) { + IdentifiableObject identifiableObject) { try (QueryManager qm = new QueryManager()) { final Team team = qm.getObjectByUuid(Team.class, identifiableObject.getUuid()); if (team == null) { diff --git a/src/main/java/org/dependencytrack/resources/v1/VexResource.java b/src/main/java/org/dependencytrack/resources/v1/VexResource.java index d8bc0d819..2fd61ec06 100644 --- a/src/main/java/org/dependencytrack/resources/v1/VexResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/VexResource.java @@ -43,7 +43,6 @@ import org.dependencytrack.resources.v1.vo.VexSubmitRequest; import org.glassfish.jersey.media.multipart.BodyPartEntity; import org.glassfish.jersey.media.multipart.FormDataBodyPart; -import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.media.multipart.FormDataParam; import javax.validation.Validator; @@ -80,7 +79,8 @@ public class VexResource extends AlpineResource { @Produces({CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON, MediaType.APPLICATION_OCTET_STREAM}) @ApiOperation( value = "Returns a VEX for a project in CycloneDX format", - response = String.class + response = String.class, + notes = "

Requires permission VULNERABILITY_ANALYSIS

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -88,7 +88,7 @@ public class VexResource extends AlpineResource { @ApiResponse(code = 404, message = "The project could not be found") }) @PermissionRequired(Permissions.Constants.VULNERABILITY_ANALYSIS) - public Response exportProjectAsCycloneDx ( + public Response exportProjectAsCycloneDx( @ApiParam(value = "The UUID of the project to export", format = "uuid", required = true) @PathParam("uuid") @ValidUuid String uuid, @ApiParam(value = "Force the resulting VEX to be downloaded as a file (defaults to 'false')") @@ -98,7 +98,7 @@ public Response exportProjectAsCycloneDx ( if (project == null) { return Response.status(Response.Status.NOT_FOUND).entity("The project could not be found.").build(); } - if (! qm.hasAccess(super.getPrincipal(), project)) { + if (!qm.hasAccess(super.getPrincipal(), project)) { return Response.status(Response.Status.FORBIDDEN).entity("Access to the specified project is forbidden").build(); } @@ -107,7 +107,7 @@ public Response exportProjectAsCycloneDx ( try { if (download) { return Response.ok(exporter.export(exporter.create(project), CycloneDXExporter.Format.JSON), MediaType.APPLICATION_OCTET_STREAM) - .header("content-disposition","attachment; filename=\"" + project.getUuid() + "-vex.cdx.json\"").build(); + .header("content-disposition", "attachment; filename=\"" + project.getUuid() + "-vex.cdx.json\"").build(); } else { return Response.ok(exporter.export(exporter.create(project), CycloneDXExporter.Format.JSON), CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON).build(); @@ -125,11 +125,16 @@ public Response exportProjectAsCycloneDx ( @ApiOperation( value = "Upload a supported VEX document", notes = """ - Expects CycloneDX and a valid project UUID. If a UUID is not specified, \ - then the projectName and projectVersion must be specified. - The VEX will be validated against the CycloneDX schema. If schema validation fails, \ - a response with problem details in RFC 9457 format will be returned. In this case, \ - the response's content type will be application/problem+json.""" +

+ Expects CycloneDX and a valid project UUID. If a UUID is not specified, + then the projectName and projectVersion must be specified. +

+

+ The VEX will be validated against the CycloneDX schema. If schema validation fails, + a response with problem details in RFC 9457 format will be returned. In this case, + the response's content type will be application/problem+json. +

+

Requires permission VULNERABILITY_ANALYSIS

""" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid VEX", response = InvalidBomProblemDetails.class), @@ -168,11 +173,16 @@ public Response uploadVex(VexSubmitRequest request) { @ApiOperation( value = "Upload a supported VEX document", notes = """ - Expects CycloneDX along and a valid project UUID. If a UUID is not specified, \ - then the projectName and projectVersion must be specified. - The VEX will be validated against the CycloneDX schema. If schema validation fails, \ - a response with problem details in RFC 9457 format will be returned. In this case, \ - the response's content type will be application/problem+json.""" +

+ Expects CycloneDX and a valid project UUID. If a UUID is not specified, + then the projectName and projectVersion must be specified. +

+

+ The VEX will be validated against the CycloneDX schema. If schema validation fails, + a response with problem details in RFC 9457 format will be returned. In this case, + the response's content type will be application/problem+json. +

+

Requires permission VULNERABILITY_ANALYSIS

""" ) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid VEX", response = InvalidBomProblemDetails.class), @@ -184,9 +194,7 @@ public Response uploadVex(VexSubmitRequest request) { public Response uploadVex(@FormDataParam("project") String projectUuid, @FormDataParam("projectName") String projectName, @FormDataParam("projectVersion") String projectVersion, - final FormDataMultiPart multiPart) { - - final List artifactParts = multiPart.getFields("vex"); + @ApiParam(type = "string") @FormDataParam("vex") final List artifactParts) { if (projectUuid != null) { try (QueryManager qm = new QueryManager()) { final Project project = qm.getObjectByUuid(Project.class, projectUuid); @@ -207,7 +215,7 @@ public Response uploadVex(@FormDataParam("project") String projectUuid, */ private Response process(QueryManager qm, Project project, String encodedVexData) { if (project != null) { - if (! qm.hasAccess(super.getPrincipal(), project)) { + if (!qm.hasAccess(super.getPrincipal(), project)) { return Response.status(Response.Status.FORBIDDEN).entity("Access to the specified project is forbidden").build(); } final byte[] decoded = Base64.getDecoder().decode(encodedVexData); @@ -224,10 +232,10 @@ private Response process(QueryManager qm, Project project, String encodedVexData * Common logic that processes a VEX given a project and list of multi-party form objects containing decoded payloads. */ private Response process(QueryManager qm, Project project, List artifactParts) { - for (final FormDataBodyPart artifactPart: artifactParts) { + for (final FormDataBodyPart artifactPart : artifactParts) { final BodyPartEntity bodyPartEntity = (BodyPartEntity) artifactPart.getEntity(); if (project != null) { - if (! qm.hasAccess(super.getPrincipal(), project)) { + if (!qm.hasAccess(super.getPrincipal(), project)) { return Response.status(Response.Status.FORBIDDEN).entity("Access to the specified project is forbidden").build(); } try (InputStream in = bodyPartEntity.getInputStream()) { diff --git a/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java b/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java index d2fb736f9..3340c99c7 100644 --- a/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/ViolationAnalysisResource.java @@ -67,7 +67,8 @@ public class ViolationAnalysisResource extends AlpineResource { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Retrieves a violation analysis trail", - response = ViolationAnalysis.class + response = ViolationAnalysis.class, + notes = "

Requires permission VIEW_POLICY_VIOLATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -101,7 +102,8 @@ public Response retrieveAnalysis(@ApiParam(value = "The UUID of the component", @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Records a violation analysis decision", - response = ViolationAnalysis.class + response = ViolationAnalysis.class, + notes = "

Requires permission VIEW_POLICY_VIOLATION

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), diff --git a/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java b/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java index f9cf19859..307d018b5 100644 --- a/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyBundleResource.java @@ -36,14 +36,15 @@ import javax.ws.rs.core.Response; @Path("/v1/policy/vulnerability/bundle") -@Api(value = "bundle", authorizations = @Authorization(value = "X-Api-Key")) +@Api(value = "policy", authorizations = @Authorization(value = "X-Api-Key")) public class VulnerabilityPolicyBundleResource extends AlpineResource { @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns vulnerability policy resource bundle", - response = VulnerabilityPolicyBundle.class + response = VulnerabilityPolicyBundle.class, + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") diff --git a/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java b/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java index 900089acf..528a3c798 100644 --- a/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/VulnerabilityPolicyResource.java @@ -72,7 +72,8 @@ public class VulnerabilityPolicyResource extends AlpineResource { value = "Returns a list of all vulnerability policies", response = VulnerabilityPolicy.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerability policies") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerability policies"), + notes = "

Requires permission POLICY_MANAGEMENT

" ) @PaginatedApi @ApiResponses(value = { @@ -92,7 +93,8 @@ public Response getVulnerabilityPolicies() { @ApiOperation( value = "Triggers policy bundle synchronization. Returns a workflow token if trigger succeeded.", response = String.class, - responseContainer = "Map" + responseContainer = "Map", + notes = "

Requires permission POLICY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 202, message = "Accepted"), @@ -144,7 +146,7 @@ public Response triggerVulnerabilityPolicyBundleSync() { return response; } catch (RuntimeException e) { if (ExceptionUtils.getRootCause(e) instanceof final PSQLException pe - && pe.getSQLState().equals(PSQLState.UNIQUE_VIOLATION.getState())) { + && pe.getSQLState().equals(PSQLState.UNIQUE_VIOLATION.getState())) { return Response .status(Response.Status.CONFLICT) .entity(Map.of("message", "Bundle synchronization is already in progress")) diff --git a/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java b/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java index 16e499774..7f591d6af 100644 --- a/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/VulnerabilityResource.java @@ -82,7 +82,8 @@ public class VulnerabilityResource extends AlpineResource { value = "Returns a list of all vulnerabilities for a specific component", response = Vulnerability.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -117,7 +118,8 @@ public Response getVulnerabilitiesByComponent(@ApiParam(value = "The UUID of the value = "Returns a list of all vulnerabilities for a specific project", response = Vulnerability.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -150,7 +152,8 @@ public Response getVulnerabilitiesByProject(@ApiParam(value = "The UUID of the p @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific vulnerability", - response = Vulnerability.class + response = Vulnerability.class, + notes = "

Requires permission VULNERABILITY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -158,7 +161,7 @@ public Response getVulnerabilitiesByProject(@ApiParam(value = "The UUID of the p }) @PermissionRequired(Permissions.Constants.VULNERABILITY_MANAGEMENT) public Response getVulnerabilityByUuid(@ApiParam(value = "The UUID of the vulnerability", format = "uuid", required = true) - @PathParam("uuid") @ValidUuid String uuid) { + @PathParam("uuid") @ValidUuid String uuid) { try (QueryManager qm = new QueryManager()) { final Vulnerability vulnerability = qm.getObjectByUuid(Vulnerability.class, uuid); if (vulnerability != null) { @@ -174,7 +177,8 @@ public Response getVulnerabilityByUuid(@ApiParam(value = "The UUID of the vulner @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Returns a specific vulnerability", - response = Vulnerability.class + response = Vulnerability.class, + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -187,7 +191,7 @@ public Response getVulnerabilityByVulnId(@PathParam("source") String source, final Vulnerability vulnerability = qm.getVulnerabilityByVulnId(source, vuln); if (vulnerability != null) { final List affectedComponents = new ArrayList<>(); - for (final VulnerableSoftware vs: vulnerability.getVulnerableSoftware()) { + for (final VulnerableSoftware vs : vulnerability.getVulnerableSoftware()) { AffectedComponent affectedComponent = new AffectedComponent(vs); final List attributions = qm.getAffectedVersionAttributions(vulnerability, vs); affectedComponent.setAffectedVersionAttributions(attributions); @@ -208,7 +212,8 @@ public Response getVulnerabilityByVulnId(@PathParam("source") String source, value = "Returns a list of all projects affected by a specific vulnerability", response = Project.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of projects"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -216,9 +221,9 @@ public Response getVulnerabilityByVulnId(@PathParam("source") String source, }) @PermissionRequired(Permissions.Constants.VIEW_PORTFOLIO) public Response getAffectedProject(@PathParam("source") String source, - @PathParam("vuln") String vuln, - @ApiParam(value = "Optionally excludes inactive projects from being returned", required = false) - @QueryParam("excludeInactive") boolean excludeInactive) { + @PathParam("vuln") String vuln, + @ApiParam(value = "Optionally excludes inactive projects from being returned", required = false) + @QueryParam("excludeInactive") boolean excludeInactive) { try (QueryManager qm = new QueryManager(getAlpineRequest())) { final Vulnerability vulnerability = qm.getVulnerabilityByVulnId(source, vuln); if (vulnerability != null) { @@ -242,7 +247,8 @@ public Response getAffectedProject(@PathParam("source") String source, value = "Returns a list of all vulnerabilities", response = Vulnerability.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @PaginatedApi @ApiResponses(value = { @@ -262,7 +268,8 @@ public Response getAllVulnerabilities() { @ApiOperation( value = "Creates a new vulnerability", response = Vulnerability.class, - code = 201 + code = 201, + notes = "

Requires permission VULNERABILITY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -305,7 +312,7 @@ public Response createVulnerability(Vulnerability jsonVulnerability) { } final List vsList = new ArrayList<>(); if (jsonVulnerability.getAffectedComponents() != null) { - for (final AffectedComponent ac: jsonVulnerability.getAffectedComponents()) { + for (final AffectedComponent ac : jsonVulnerability.getAffectedComponents()) { final VulnerableSoftware vs = ac.toVulnerableSoftware(); if (vs != null) { vsList.add(vs); @@ -323,7 +330,7 @@ public Response createVulnerability(Vulnerability jsonVulnerability) { } else { return Response.status(Response.Status.CONFLICT).entity("A vulnerability with the specified vulnId already exists.").build(); } - } catch (MissingFactorException|IllegalArgumentException exception) { + } catch (MissingFactorException | IllegalArgumentException exception) { return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).build(); } } @@ -333,7 +340,8 @@ public Response createVulnerability(Vulnerability jsonVulnerability) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Updates an internal vulnerability", - response = Project.class + response = Project.class, + notes = "

Requires permission VULNERABILITY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -368,7 +376,7 @@ public Response updateVulnerability(Vulnerability jsonVuln) { final List cweIds = new ArrayList<>(); if (jsonVuln.getCwes() != null) { - for (int i=0; i vsListOld = qm.getVulnerableSoftwareByVulnId(vulnerability.getSource(), vulnerability.getVulnId()); List vsList = new ArrayList<>(); if (jsonVuln.getAffectedComponents() != null) { - for (final AffectedComponent ac: jsonVuln.getAffectedComponents()) { + for (final AffectedComponent ac : jsonVuln.getAffectedComponents()) { final VulnerableSoftware vs = ac.toVulnerableSoftware(); if (vs != null) { vsList.add(vs); @@ -412,7 +420,8 @@ public Response updateVulnerability(Vulnerability jsonVuln) { @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Deletes a vulnerability", - code = 204 + code = 204, + notes = "

Requires permission VULNERABILITY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -449,7 +458,8 @@ public Response deleteVulnerability( @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Generates an internal vulnerability identifier", - response = String.class + response = String.class, + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") @@ -505,7 +515,8 @@ public void recalculateScoresAndSeverityFromVectors(Vulnerability vuln) throws M @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Assigns a vulnerability to a component" + value = "Assigns a vulnerability to a component", + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -543,7 +554,8 @@ public Response assignVulnerability(@ApiParam(value = "The vulnerability source" @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Assigns a vulnerability to a component" + value = "Assigns a vulnerability to a component", + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -579,7 +591,8 @@ public Response assignVulnerability(@ApiParam(value = "The UUID of the vulnerabi @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Removes assignment of a vulnerability from a component" + value = "Removes assignment of a vulnerability from a component", + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -617,7 +630,8 @@ public Response unassignVulnerability(@ApiParam(value = "The vulnerability sourc @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Removes assignment of a vulnerability from a component" + value = "Removes assignment of a vulnerability from a component", + notes = "

Requires permission PORTFOLIO_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -653,7 +667,8 @@ public Response unassignVulnerability(@ApiParam(value = "The UUID of the vulnera @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( - value = "Updates tags for a vulnerability" + value = "Updates tags for a vulnerability", + notes = "

Requires permission VULNERABILITY_MANAGEMENT

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @@ -683,7 +698,8 @@ public Response updateVulnerabilityTags(List tags, value = "Returns a list of all vulnerabilities by tag", response = Vulnerability.class, responseContainer = "List", - responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities with the tag") + responseHeaders = @ResponseHeader(name = TOTAL_COUNT_HEADER, response = Long.class, description = "The total number of vulnerabilities with the tag"), + notes = "

Requires permission VIEW_PORTFOLIO

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized") diff --git a/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java b/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java index 782847ba0..23fcfda43 100644 --- a/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java +++ b/src/main/java/org/dependencytrack/resources/v1/WorkflowResource.java @@ -52,13 +52,14 @@ public class WorkflowResource { @ApiOperation( value = "Retrieves workflow states associated with the token received from bom upload .", response = WorkflowState.class, - responseContainer = "List" + responseContainer = "List", + notes = "

Requires permission BOM_UPLOAD

" ) @ApiResponses(value = { @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 404, message = "Workflow does not exist") }) - @PermissionRequired(Permissions.Constants.BOM_UPLOAD) + @PermissionRequired(Permissions.Constants.BOM_UPLOAD) // TODO: Should be a more generic permission. public Response getWorkflowStates( @ApiParam(value = "The UUID of the token to query", required = true) @PathParam("uuid") @ValidUuid String uuid) { diff --git a/src/main/java/org/dependencytrack/resources/v1/problems/ProblemDetails.java b/src/main/java/org/dependencytrack/resources/v1/problems/ProblemDetails.java index fbfedd555..03586f6ea 100644 --- a/src/main/java/org/dependencytrack/resources/v1/problems/ProblemDetails.java +++ b/src/main/java/org/dependencytrack/resources/v1/problems/ProblemDetails.java @@ -45,7 +45,8 @@ public class ProblemDetails { @ApiModelProperty( value = "HTTP status code generated by the origin server for this occurrence of the problem", - example = "400" + example = "400", + required = true ) private Integer status; @@ -58,7 +59,8 @@ public class ProblemDetails { @ApiModelProperty( value = "Human-readable explanation specific to this occurrence of the problem", - example = "Example detail" + example = "Example detail", + required = true ) private String detail; diff --git a/src/main/java/org/dependencytrack/resources/v1/vo/BomSubmitRequest.java b/src/main/java/org/dependencytrack/resources/v1/vo/BomSubmitRequest.java index 891a7bb20..17830597f 100644 --- a/src/main/java/org/dependencytrack/resources/v1/vo/BomSubmitRequest.java +++ b/src/main/java/org/dependencytrack/resources/v1/vo/BomSubmitRequest.java @@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -76,13 +77,13 @@ public BomSubmitRequest(String project, } @JsonCreator - public BomSubmitRequest(@JsonProperty(value = "project", required = false) String project, - @JsonProperty(value = "projectName", required = false) String projectName, - @JsonProperty(value = "projectVersion", required = false) String projectVersion, - @JsonProperty(value = "autoCreate", required = false) boolean autoCreate, - @JsonProperty(value = "parentUUID", required = false) String parentUUID, - @JsonProperty(value = "parentName", required = false) String parentName, - @JsonProperty(value = "parentVersion", required = false) String parentVersion, + public BomSubmitRequest(@JsonProperty(value = "project") String project, + @JsonProperty(value = "projectName") String projectName, + @JsonProperty(value = "projectVersion") String projectVersion, + @JsonProperty(value = "autoCreate") boolean autoCreate, + @JsonProperty(value = "parentUUID") String parentUUID, + @JsonProperty(value = "parentName") String parentName, + @JsonProperty(value = "parentVersion") String parentVersion, @JsonProperty(value = "bom", required = true) String bom) { this.project = project; this.projectName = projectName; @@ -94,26 +95,32 @@ public BomSubmitRequest(@JsonProperty(value = "project", required = false) Strin this.bom = bom; } + @ApiModelProperty(example = "38640b33-4ba9-4733-bdab-cbfc40c6f8aa") public String getProject() { return project; } + @ApiModelProperty(example = "Example Application") public String getProjectName() { return projectName; } + @ApiModelProperty(example = "1.0.0") public String getProjectVersion() { return projectVersion; } + @ApiModelProperty(example = "5341f53c-611b-4388-9d9c-731026dc5eec") public String getParentUUID() { return parentUUID; } + @ApiModelProperty(example = "Example Application Parent") public String getParentName() { return parentName; } + @ApiModelProperty(example = "1.0.0") public String getParentVersion() { return parentVersion; } @@ -122,6 +129,15 @@ public boolean isAutoCreate() { return autoCreate; } + @ApiModelProperty( + value = "Base64 encoded BOM", + required = true, + example = """ + ewogICJib21Gb3JtYXQiOiAiQ3ljbG9uZURYIiwKICAic3BlY1ZlcnNpb24iOiAi\ + MS40IiwKICAiY29tcG9uZW50cyI6IFsKICAgIHsKICAgICAgInR5cGUiOiAibGli\ + cmFyeSIsCiAgICAgICJuYW1lIjogImFjbWUtbGliIiwKICAgICAgInZlcnNpb24i\ + OiAiMS4wLjAiCiAgICB9CiAgXQp9""" + ) public String getBom() { return bom; } diff --git a/src/test/java/org/dependencytrack/resources/v1/OsvEcosystemResourceTest.java b/src/test/java/org/dependencytrack/resources/v1/IntegrationResourceTest.java similarity index 96% rename from src/test/java/org/dependencytrack/resources/v1/OsvEcosystemResourceTest.java rename to src/test/java/org/dependencytrack/resources/v1/IntegrationResourceTest.java index 33f719a59..2d59768a4 100644 --- a/src/test/java/org/dependencytrack/resources/v1/OsvEcosystemResourceTest.java +++ b/src/test/java/org/dependencytrack/resources/v1/IntegrationResourceTest.java @@ -35,11 +35,11 @@ import static org.dependencytrack.model.ConfigPropertyConstants.VULNERABILITY_SOURCE_GOOGLE_OSV_BASE_URL; import static org.dependencytrack.model.ConfigPropertyConstants.VULNERABILITY_SOURCE_GOOGLE_OSV_ENABLED; -public class OsvEcosystemResourceTest extends ResourceTest { +public class IntegrationResourceTest extends ResourceTest { @ClassRule public static JerseyTestRule jersey = new JerseyTestRule( - new ResourceConfig(OsvEcosytemResource.class) + new ResourceConfig(IntegrationResource.class) .register(ApiFilter.class) .register(AuthenticationFilter.class));