From a7119e8d237334099edeeabad689880157466f2b Mon Sep 17 00:00:00 2001 From: nscuro Date: Sat, 18 May 2024 11:55:28 +0200 Subject: [PATCH] Fix OpenAPI types of UNIX timestamp fields Fields of type `Date` that are not explicitly serialized with `Iso8601DateSerializer` are automatically serialized as UNIX epoch timestamp in milliseconds. However the OpenAPI spec declared them to be of type `string` in `date-time` format, which is incorrect. Instead of changing the field's actual type, causing a breaking change, provide a type hint to the OpenAPI generator. Fixes #1276 Fixes #2591 Signed-off-by: nscuro --- .../model/AffectedVersionAttribution.java | 3 +++ .../org/dependencytrack/model/AnalysisComment.java | 2 ++ src/main/java/org/dependencytrack/model/Bom.java | 2 ++ .../dependencytrack/model/DependencyMetrics.java | 7 +++++++ .../dependencytrack/model/FindingAttribution.java | 2 ++ .../org/dependencytrack/model/PolicyViolation.java | 2 ++ .../org/dependencytrack/model/PortfolioMetrics.java | 12 ++++++------ .../java/org/dependencytrack/model/Project.java | 1 + .../org/dependencytrack/model/ProjectMetrics.java | 13 +++++++------ .../model/RepositoryMetaComponent.java | 3 +++ src/main/java/org/dependencytrack/model/Vex.java | 3 +++ .../model/ViolationAnalysisComment.java | 2 ++ .../dependencytrack/model/VulnerabilityMetrics.java | 2 ++ .../resources/v1/problems/ProblemDetails.java | 6 +++--- .../v1/vo/IsTokenBeingProcessedResponse.java | 2 +- 15 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/dependencytrack/model/AffectedVersionAttribution.java b/src/main/java/org/dependencytrack/model/AffectedVersionAttribution.java index 4f9d59cfe..781a6324f 100644 --- a/src/main/java/org/dependencytrack/model/AffectedVersionAttribution.java +++ b/src/main/java/org/dependencytrack/model/AffectedVersionAttribution.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import org.dependencytrack.model.Vulnerability.Source; import javax.jdo.annotations.Column; @@ -64,10 +65,12 @@ public class AffectedVersionAttribution implements Serializable { @Persistent @Column(name = "FIRST_SEEN", allowsNull = "false") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date firstSeen; @Persistent @Column(name = "LAST_SEEN", allowsNull = "false") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date lastSeen; @Persistent diff --git a/src/main/java/org/dependencytrack/model/AnalysisComment.java b/src/main/java/org/dependencytrack/model/AnalysisComment.java index 19627b898..74d3286a4 100644 --- a/src/main/java/org/dependencytrack/model/AnalysisComment.java +++ b/src/main/java/org/dependencytrack/model/AnalysisComment.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; @@ -57,6 +58,7 @@ public class AnalysisComment implements Serializable { @Persistent(defaultFetchGroup = "true") @Column(name = "TIMESTAMP", allowsNull = "false") @NotNull + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date timestamp; @Persistent(defaultFetchGroup = "true") diff --git a/src/main/java/org/dependencytrack/model/Bom.java b/src/main/java/org/dependencytrack/model/Bom.java index 437a02fe2..1103298e8 100644 --- a/src/main/java/org/dependencytrack/model/Bom.java +++ b/src/main/java/org/dependencytrack/model/Bom.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; @@ -73,6 +74,7 @@ public String getFormatLongName() { @Persistent @Column(name = "IMPORTED", allowsNull = "false") @NotNull + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date imported; @Persistent diff --git a/src/main/java/org/dependencytrack/model/DependencyMetrics.java b/src/main/java/org/dependencytrack/model/DependencyMetrics.java index f92d22480..ce0e0d3a8 100644 --- a/src/main/java/org/dependencytrack/model/DependencyMetrics.java +++ b/src/main/java/org/dependencytrack/model/DependencyMetrics.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; @@ -61,18 +62,22 @@ public class DependencyMetrics implements Serializable { @Persistent @Column(name = "CRITICAL") + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int critical; @Persistent @Column(name = "HIGH") + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int high; @Persistent @Column(name = "MEDIUM") + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int medium; @Persistent @Column(name = "LOW") + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int low; @Persistent @@ -167,12 +172,14 @@ public class DependencyMetrics implements Serializable { @Column(name = "FIRST_OCCURRENCE", allowsNull = "false") @NotNull @Index(name = "DEPENDENCYMETRICS_FIRST_OCCURRENCE_IDX") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date firstOccurrence; @Persistent @Column(name = "LAST_OCCURRENCE", allowsNull = "false") @NotNull @Index(name = "DEPENDENCYMETRICS_LAST_OCCURRENCE_IDX") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date lastOccurrence; public long getId() { diff --git a/src/main/java/org/dependencytrack/model/FindingAttribution.java b/src/main/java/org/dependencytrack/model/FindingAttribution.java index f5e6a2555..202b9f337 100644 --- a/src/main/java/org/dependencytrack/model/FindingAttribution.java +++ b/src/main/java/org/dependencytrack/model/FindingAttribution.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import org.dependencytrack.tasks.scanners.AnalyzerIdentity; import javax.jdo.annotations.Column; @@ -55,6 +56,7 @@ public class FindingAttribution implements Serializable { @Persistent @Column(name = "ATTRIBUTED_ON", allowsNull = "false") @NotNull + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date attributedOn; @Persistent diff --git a/src/main/java/org/dependencytrack/model/PolicyViolation.java b/src/main/java/org/dependencytrack/model/PolicyViolation.java index 7a2b1614a..4758286d7 100644 --- a/src/main/java/org/dependencytrack/model/PolicyViolation.java +++ b/src/main/java/org/dependencytrack/model/PolicyViolation.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; @@ -79,6 +80,7 @@ public enum Type { @Persistent @Column(name = "TIMESTAMP", allowsNull = "false") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date timestamp; @Persistent diff --git a/src/main/java/org/dependencytrack/model/PortfolioMetrics.java b/src/main/java/org/dependencytrack/model/PortfolioMetrics.java index 4136e56b2..2e0a9b528 100644 --- a/src/main/java/org/dependencytrack/model/PortfolioMetrics.java +++ b/src/main/java/org/dependencytrack/model/PortfolioMetrics.java @@ -52,22 +52,22 @@ public class PortfolioMetrics implements Serializable { @Persistent @Column(name = "CRITICAL") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int critical; @Persistent @Column(name = "HIGH") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int high; @Persistent @Column(name = "MEDIUM") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int medium; @Persistent @Column(name = "LOW") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int low; @Persistent @@ -178,14 +178,14 @@ public class PortfolioMetrics implements Serializable { @Column(name = "FIRST_OCCURRENCE", allowsNull = "false") @NotNull @Index(name = "PORTFOLIOMETRICS_FIRST_OCCURRENCE_IDX") - @Schema(requiredMode = Schema.RequiredMode.REQUIRED, type = "number") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date firstOccurrence; @Persistent @Column(name = "LAST_OCCURRENCE", allowsNull = "false") @NotNull @Index(name = "PORTFOLIOMETRICS_LAST_OCCURRENCE_IDX") - @Schema(requiredMode = Schema.RequiredMode.REQUIRED, type = "number") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date lastOccurrence; public long getId() { diff --git a/src/main/java/org/dependencytrack/model/Project.java b/src/main/java/org/dependencytrack/model/Project.java index f8fcae99d..6a073a094 100644 --- a/src/main/java/org/dependencytrack/model/Project.java +++ b/src/main/java/org/dependencytrack/model/Project.java @@ -244,6 +244,7 @@ public enum FetchGroup { @Persistent @Index(name = "PROJECT_LASTBOMIMPORT_IDX") @Column(name = "LAST_BOM_IMPORTED") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date lastBomImport; /** diff --git a/src/main/java/org/dependencytrack/model/ProjectMetrics.java b/src/main/java/org/dependencytrack/model/ProjectMetrics.java index e6272824d..22780f965 100644 --- a/src/main/java/org/dependencytrack/model/ProjectMetrics.java +++ b/src/main/java/org/dependencytrack/model/ProjectMetrics.java @@ -51,27 +51,28 @@ public class ProjectMetrics implements Serializable { @Persistent @Column(name = "PROJECT_ID", allowsNull = "false") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private Project project; @Persistent @Column(name = "CRITICAL") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int critical; @Persistent @Column(name = "HIGH") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int high; @Persistent @Column(name = "MEDIUM") - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int medium; @Persistent @Column(name = "LOW") @NotNull + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private int low; @Persistent @@ -174,14 +175,14 @@ public class ProjectMetrics implements Serializable { @Column(name = "FIRST_OCCURRENCE", allowsNull = "false") @NotNull @Index(name = "PROJECTMETRICS_FIRST_OCCURRENCE_IDX") - @Schema(requiredMode = Schema.RequiredMode.REQUIRED, type = "number") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date firstOccurrence; @Persistent @Column(name = "LAST_OCCURRENCE", allowsNull = "false") @NotNull @Index(name = "PROJECTMETRICS_LAST_OCCURRENCE_IDX") - @Schema(requiredMode = Schema.RequiredMode.REQUIRED, type = "number") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date lastOccurrence; public long getId() { diff --git a/src/main/java/org/dependencytrack/model/RepositoryMetaComponent.java b/src/main/java/org/dependencytrack/model/RepositoryMetaComponent.java index af0268f39..4081bc555 100644 --- a/src/main/java/org/dependencytrack/model/RepositoryMetaComponent.java +++ b/src/main/java/org/dependencytrack/model/RepositoryMetaComponent.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; @@ -85,6 +86,7 @@ public class RepositoryMetaComponent implements Serializable { */ @Persistent @Column(name = "PUBLISHED") + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date published; /** @@ -94,6 +96,7 @@ public class RepositoryMetaComponent implements Serializable { @Column(name = "LAST_CHECK", allowsNull = "false") @Index(name = "REPOSITORY_META_COMPONENT_LASTCHECK_IDX") @NotNull + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date lastCheck; diff --git a/src/main/java/org/dependencytrack/model/Vex.java b/src/main/java/org/dependencytrack/model/Vex.java index f75ed84ea..55a1d8b14 100644 --- a/src/main/java/org/dependencytrack/model/Vex.java +++ b/src/main/java/org/dependencytrack/model/Vex.java @@ -20,6 +20,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; + import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; @@ -71,6 +73,7 @@ public String getFormatLongName() { @Persistent @Column(name = "IMPORTED", allowsNull = "false") @NotNull + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date imported; @Persistent diff --git a/src/main/java/org/dependencytrack/model/ViolationAnalysisComment.java b/src/main/java/org/dependencytrack/model/ViolationAnalysisComment.java index 63e78fa4e..16d642eb4 100644 --- a/src/main/java/org/dependencytrack/model/ViolationAnalysisComment.java +++ b/src/main/java/org/dependencytrack/model/ViolationAnalysisComment.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; @@ -57,6 +58,7 @@ public class ViolationAnalysisComment implements Serializable { @Persistent(defaultFetchGroup = "true") @Column(name = "TIMESTAMP", allowsNull = "false") @NotNull + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date timestamp; @Persistent(defaultFetchGroup = "true") diff --git a/src/main/java/org/dependencytrack/model/VulnerabilityMetrics.java b/src/main/java/org/dependencytrack/model/VulnerabilityMetrics.java index 413ceee95..25658e770 100644 --- a/src/main/java/org/dependencytrack/model/VulnerabilityMetrics.java +++ b/src/main/java/org/dependencytrack/model/VulnerabilityMetrics.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import javax.jdo.annotations.Column; import javax.jdo.annotations.IdGeneratorStrategy; @@ -62,6 +63,7 @@ public class VulnerabilityMetrics implements Serializable { @Persistent @Column(name = "MEASURED_AT", allowsNull = "false") @NotNull + @Schema(type = "integer", format = "int64", requiredMode = Schema.RequiredMode.REQUIRED, description = "UNIX epoch timestamp in milliseconds") private Date measuredAt; public long getId() { 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 f5c139196..eabf4a902 100644 --- a/src/main/java/org/dependencytrack/resources/v1/problems/ProblemDetails.java +++ b/src/main/java/org/dependencytrack/resources/v1/problems/ProblemDetails.java @@ -45,21 +45,21 @@ public class ProblemDetails { @Schema( description = "HTTP status code generated by the origin server for this occurrence of the problem", example = "400", - required = true + requiredMode = Schema.RequiredMode.REQUIRED ) private Integer status; @Schema( description = "Short, human-readable summary of the problem type", example = "Example title", - required = true + requiredMode = Schema.RequiredMode.REQUIRED ) private String title; @Schema( description = "Human-readable explanation specific to this occurrence of the problem", example = "Example detail", - required = true + requiredMode = Schema.RequiredMode.REQUIRED ) private String detail; diff --git a/src/main/java/org/dependencytrack/resources/v1/vo/IsTokenBeingProcessedResponse.java b/src/main/java/org/dependencytrack/resources/v1/vo/IsTokenBeingProcessedResponse.java index 4e354c936..1aae286d3 100644 --- a/src/main/java/org/dependencytrack/resources/v1/vo/IsTokenBeingProcessedResponse.java +++ b/src/main/java/org/dependencytrack/resources/v1/vo/IsTokenBeingProcessedResponse.java @@ -26,7 +26,7 @@ public class IsTokenBeingProcessedResponse implements Serializable { private static final long serialVersionUID = -7592468766586686855L; - @Schema(required = true) + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) private Boolean processing; public void setProcessing(Boolean processing) {