Skip to content

Commit

Permalink
Merge pull request #3969 from 2000rosser/issue-3936
Browse files Browse the repository at this point in the history
Add support for authors field
  • Loading branch information
nscuro authored Aug 15, 2024
2 parents ca3ef44 + 55e5a71 commit c63745b
Show file tree
Hide file tree
Showing 15 changed files with 250 additions and 36 deletions.
36 changes: 28 additions & 8 deletions src/main/java/org/dependencytrack/model/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.dependencytrack.model.validation.ValidSpdxExpression;
import org.dependencytrack.persistence.converter.OrganizationalContactsJsonConverter;
import org.dependencytrack.persistence.converter.OrganizationalEntityJsonConverter;
import org.dependencytrack.resources.v1.serializers.CustomPackageURLSerializer;
import org.dependencytrack.parser.cyclonedx.util.ModelConverter;

import jakarta.json.JsonObject;
import jakarta.validation.constraints.NotBlank;
Expand Down Expand Up @@ -109,10 +111,10 @@ public enum FetchGroup {
@JsonIgnore
private long id;

@Persistent
@Column(name = "AUTHOR", jdbcType = "CLOB")
@Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The author may only contain printable characters")
private String author;
@Persistent(defaultFetchGroup = "true")
@Convert(OrganizationalContactsJsonConverter.class)
@Column(name = "AUTHORS", jdbcType = "CLOB", allowsNull = "true")
private List<OrganizationalContact> authors;

@Persistent
@Column(name = "PUBLISHER", jdbcType = "VARCHAR")
Expand Down Expand Up @@ -386,18 +388,36 @@ public void setId(long id) {
this.id = id;
}

public String getAuthor() {
return author;
public List<OrganizationalContact> getAuthors() {
return authors;
}

public void setAuthor(String author) {
this.author = author;
public void setAuthors(List<OrganizationalContact> authors) {
this.authors = authors;
}

public String getPublisher() {
return publisher;
}

@Deprecated
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public String getAuthor(){
return ModelConverter.convertContactsToString(this.authors);
}

@Deprecated
public void setAuthor(String author){
if(this.authors==null){
this.authors = new ArrayList<>();
} else {
this.authors.clear();
}
this.authors.add(new OrganizationalContact() {{
setName(author);
}});
}

public void setPublisher(String publisher) {
this.publisher = publisher;
}
Expand Down
41 changes: 30 additions & 11 deletions src/main/java/org/dependencytrack/model/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import io.swagger.v3.oas.annotations.media.Schema;

import org.dependencytrack.parser.cyclonedx.util.ModelConverter;
import org.dependencytrack.persistence.converter.OrganizationalContactsJsonConverter;
import org.dependencytrack.persistence.converter.OrganizationalEntityJsonConverter;
import org.dependencytrack.resources.v1.serializers.CustomPackageURLSerializer;

Expand Down Expand Up @@ -74,7 +77,7 @@
@FetchGroups({
@FetchGroup(name = "ALL", members = {
@Persistent(name = "name"),
@Persistent(name = "author"),
@Persistent(name = "authors"),
@Persistent(name = "publisher"),
@Persistent(name = "supplier"),
@Persistent(name = "group"),
Expand Down Expand Up @@ -125,12 +128,10 @@ public enum FetchGroup {
@JsonIgnore
private long id;

@Persistent
@Column(name = "AUTHOR", jdbcType = "VARCHAR")
@Size(max = 255)
@JsonDeserialize(using = TrimmedStringDeserializer.class)
@Pattern(regexp = RegexSequence.Definition.PRINTABLE_CHARS, message = "The author may only contain printable characters")
private String author;
@Persistent(defaultFetchGroup = "true")
@Convert(OrganizationalContactsJsonConverter.class)
@Column(name = "AUTHORS", jdbcType = "CLOB", allowsNull = "true")
private List<OrganizationalContact> authors;

@Persistent
@Column(name = "PUBLISHER", jdbcType = "VARCHAR")
Expand Down Expand Up @@ -297,12 +298,30 @@ public void setId(long id) {
this.id = id;
}

public String getAuthor() {
return author;
public List<OrganizationalContact> getAuthors() {
return authors;
}

public void setAuthor(String author) {
this.author = author;
public void setAuthors(List<OrganizationalContact> authors) {
this.authors = authors;
}

@Deprecated
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public String getAuthor(){
return ModelConverter.convertContactsToString(this.authors);
}

@Deprecated
public void setAuthor(String author){
if(this.authors==null){
this.authors = new ArrayList<>();
} else{
this.authors.clear();
}
this.authors.add(new OrganizationalContact() {{
setName(author);
}});
}

public String getPublisher() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ public static Project convertToProject(final org.cyclonedx.model.Metadata cdxMet
public static Project convertToProject(final org.cyclonedx.model.Component cdxComponent) {
final var project = new Project();
project.setBomRef(useOrGenerateRandomBomRef(cdxComponent.getBomRef()));
project.setAuthor(trimToNull(cdxComponent.getAuthor()));
project.setPublisher(trimToNull(cdxComponent.getPublisher()));
project.setSupplier(convert(cdxComponent.getSupplier()));
project.setClassifier(convertClassifier(cdxComponent.getType()).orElse(Classifier.APPLICATION));
Expand All @@ -126,6 +125,17 @@ public static Project convertToProject(final org.cyclonedx.model.Component cdxCo
project.setDescription(trimToNull(cdxComponent.getDescription()));
project.setExternalReferences(convertExternalReferences(cdxComponent.getExternalReferences()));

List<OrganizationalContact> contacts = new ArrayList<>();
if(cdxComponent.getAuthor()!=null){
contacts.add(new OrganizationalContact() {{
setName(cdxComponent.getAuthor());
}});
}
if(cdxComponent.getAuthors()!=null){
contacts.addAll(convertCdxContacts(cdxComponent.getAuthors()));
}
project.setAuthors(contacts);

if (cdxComponent.getPurl() != null) {
try {
final var purl = new PackageURL(cdxComponent.getPurl());
Expand Down Expand Up @@ -153,7 +163,6 @@ public static List<Component> convertComponents(final List<org.cyclonedx.model.C
public static Component convertComponent(final org.cyclonedx.model.Component cdxComponent) {
final var component = new Component();
component.setBomRef(useOrGenerateRandomBomRef(cdxComponent.getBomRef()));
component.setAuthor(trimToNull(cdxComponent.getAuthor()));
component.setPublisher(trimToNull(cdxComponent.getPublisher()));
component.setSupplier(convert(cdxComponent.getSupplier()));
component.setClassifier(convertClassifier(cdxComponent.getType()).orElse(Classifier.LIBRARY));
Expand All @@ -166,6 +175,17 @@ public static Component convertComponent(final org.cyclonedx.model.Component cdx
component.setExternalReferences(convertExternalReferences(cdxComponent.getExternalReferences()));
component.setProperties(convertToComponentProperties(cdxComponent.getProperties()));

List<OrganizationalContact> contacts = new ArrayList<>();
if(cdxComponent.getAuthor()!=null){
contacts.add(new OrganizationalContact() {{
setName(cdxComponent.getAuthor());
}});
}
if(cdxComponent.getAuthors()!=null){
contacts.addAll(convertCdxContacts(cdxComponent.getAuthors()));
}
component.setAuthors(contacts);

if (cdxComponent.getPurl() != null) {
try {
final var purl = new PackageURL(cdxComponent.getPurl());
Expand Down Expand Up @@ -525,7 +545,7 @@ public static org.cyclonedx.model.Component convert(final QueryManager qm, final
cycloneComponent.setDescription(StringUtils.trimToNull(component.getDescription()));
cycloneComponent.setCopyright(StringUtils.trimToNull(component.getCopyright()));
cycloneComponent.setCpe(StringUtils.trimToNull(component.getCpe()));
cycloneComponent.setAuthor(StringUtils.trimToNull(component.getAuthor()));
cycloneComponent.setAuthor(StringUtils.trimToNull(convertContactsToString(component.getAuthors())));
cycloneComponent.setSupplier(convert(component.getSupplier()));
cycloneComponent.setProperties(convert(component.getProperties()));

Expand Down Expand Up @@ -654,6 +674,23 @@ private static <T extends IConfigProperty> List<org.cyclonedx.model.Property> co
return cdxProperties;
}

public static String convertContactsToString(List<OrganizationalContact> authors) {
if (authors == null || authors.isEmpty()) {
return "";
}
StringBuilder stringBuilder = new StringBuilder();
for (OrganizationalContact author : authors) {
if (author != null && author.getName() != null) {
stringBuilder.append(author.getName()).append(", ");
}
}
//remove trailing comma and space
if (stringBuilder.length() > 0) {
stringBuilder.setLength(stringBuilder.length() - 2);
}
return stringBuilder.toString();
}

public static org.cyclonedx.model.Metadata createMetadata(final Project project) {
final org.cyclonedx.model.Metadata metadata = new org.cyclonedx.model.Metadata();
final org.cyclonedx.model.Tool tool = new org.cyclonedx.model.Tool();
Expand All @@ -666,7 +703,7 @@ public static org.cyclonedx.model.Metadata createMetadata(final Project project)

final org.cyclonedx.model.Component cycloneComponent = new org.cyclonedx.model.Component();
cycloneComponent.setBomRef(project.getUuid().toString());
cycloneComponent.setAuthor(StringUtils.trimToNull(project.getAuthor()));
cycloneComponent.setAuthor(StringUtils.trimToNull(convertContactsToString(project.getAuthors())));
cycloneComponent.setPublisher(StringUtils.trimToNull(project.getPublisher()));
cycloneComponent.setGroup(StringUtils.trimToNull(project.getGroup()));
cycloneComponent.setName(StringUtils.trimToNull(project.getName()));
Expand Down Expand Up @@ -704,6 +741,7 @@ public static org.cyclonedx.model.Metadata createMetadata(final Project project)
cycloneComponent.setExternalReferences(references);
}
cycloneComponent.setSupplier(convert(project.getSupplier()));
cycloneComponent.setAuthors(convertContacts(project.getAuthors()));

// NB: Project properties are currently used to configure integrations
// such as Defect Dojo. They can also contain encrypted values that most
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ public Component cloneComponent(Component sourceComponent, Project destinationPr
component.setLicenseExpression(sourceComponent.getLicenseExpression());
component.setLicenseUrl(sourceComponent.getLicenseUrl());
component.setResolvedLicense(sourceComponent.getResolvedLicense());
component.setAuthor(sourceComponent.getAuthor());
component.setAuthors(sourceComponent.getAuthors());
component.setSupplier(sourceComponent.getSupplier());
// TODO Add support for parent component and children components
component.setProject(destinationProject);
Expand Down Expand Up @@ -412,7 +412,7 @@ public Component updateComponent(Component transientComponent, boolean commitInd
component.setCpe(transientComponent.getCpe());
component.setPurl(transientComponent.getPurl());
component.setInternal(transientComponent.isInternal());
component.setAuthor(transientComponent.getAuthor());
component.setAuthors(transientComponent.getAuthors());
component.setSupplier(transientComponent.getSupplier());
component.setExternalReferences(transientComponent.getExternalReferences());
final Component result = persist(component);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ public Project createProject(final Project project, List<Tag> tags, boolean comm
@Override
public Project updateProject(Project transientProject, boolean commitIndex) {
final Project project = getObjectByUuid(Project.class, transientProject.getUuid());
project.setAuthor(transientProject.getAuthor());
project.setAuthors(transientProject.getAuthors());
project.setPublisher(transientProject.getPublisher());
project.setManufacturer(transientProject.getManufacturer());
project.setSupplier(transientProject.getSupplier());
Expand Down Expand Up @@ -603,7 +603,7 @@ public Project clone(
return null;
}
Project project = new Project();
project.setAuthor(source.getAuthor());
project.setAuthors(source.getAuthors());
project.setManufacturer(source.getManufacturer());
project.setSupplier(source.getSupplier());
project.setPublisher(source.getPublisher());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ public Response createComponent(@Parameter(description = "The UUID of the projec
@PathParam("uuid") @ValidUuid String uuid, Component jsonComponent) {
final Validator validator = super.getValidator();
failOnValidationError(
validator.validateProperty(jsonComponent, "authors"),
validator.validateProperty(jsonComponent, "author"),
validator.validateProperty(jsonComponent, "publisher"),
validator.validateProperty(jsonComponent, "name"),
Expand Down Expand Up @@ -323,7 +324,7 @@ public Response createComponent(@Parameter(description = "The UUID of the projec
final License resolvedLicense = qm.getLicense(jsonComponent.getLicense());
Component component = new Component();
component.setProject(project);
component.setAuthor(StringUtils.trimToNull(jsonComponent.getAuthor()));
component.setAuthors(jsonComponent.getAuthors());
component.setPublisher(StringUtils.trimToNull(jsonComponent.getPublisher()));
component.setName(StringUtils.trimToNull(jsonComponent.getName()));
component.setVersion(StringUtils.trimToNull(jsonComponent.getVersion()));
Expand Down Expand Up @@ -426,7 +427,7 @@ public Response updateComponent(Component jsonComponent) {
if (name != null) {
component.setName(name);
}
component.setAuthor(StringUtils.trimToNull(jsonComponent.getAuthor()));
component.setAuthors(jsonComponent.getAuthors());
component.setPublisher(StringUtils.trimToNull(jsonComponent.getPublisher()));
component.setVersion(StringUtils.trimToNull(jsonComponent.getVersion()));
component.setGroup(StringUtils.trimToNull(jsonComponent.getGroup()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ public Response createProject(Project jsonProject) {
final Validator validator = super.getValidator();
failOnValidationError(
validator.validateProperty(jsonProject, "author"),
validator.validateProperty(jsonProject, "authors"),
validator.validateProperty(jsonProject, "publisher"),
validator.validateProperty(jsonProject, "group"),
validator.validateProperty(jsonProject, "name"),
Expand Down Expand Up @@ -353,7 +354,7 @@ public Response createProject(Project jsonProject) {
public Response updateProject(Project jsonProject) {
final Validator validator = super.getValidator();
failOnValidationError(
validator.validateProperty(jsonProject, "author"),
validator.validateProperty(jsonProject, "authors"),
validator.validateProperty(jsonProject, "publisher"),
validator.validateProperty(jsonProject, "group"),
validator.validateProperty(jsonProject, "name"),
Expand Down Expand Up @@ -430,6 +431,7 @@ public Response patchProject(
final Validator validator = getValidator();
failOnValidationError(
validator.validateProperty(jsonProject, "author"),
validator.validateProperty(jsonProject, "authors"),
validator.validateProperty(jsonProject, "publisher"),
validator.validateProperty(jsonProject, "group"),
jsonProject.getName() != null ? validator.validateProperty(jsonProject, "name") : Set.of(),
Expand All @@ -455,7 +457,7 @@ public Response patchProject(
if (modified && qm.doesProjectExist(project.getName(), project.getVersion())) {
return Response.status(Response.Status.CONFLICT).entity("A project with the specified name and version already exists.").build();
}
modified |= setIfDifferent(jsonProject, project, Project::getAuthor, Project::setAuthor);
modified |= setIfDifferent(jsonProject, project, Project::getAuthors, Project::setAuthors);
modified |= setIfDifferent(jsonProject, project, Project::getPublisher, Project::setPublisher);
modified |= setIfDifferent(jsonProject, project, Project::getGroup, Project::setGroup);
modified |= setIfDifferent(jsonProject, project, Project::getDescription, Project::setDescription);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ private Project processProject(
boolean hasChanged = false;
if (project != null) {
persistentProject.setBomRef(project.getBomRef()); // Transient
hasChanged |= applyIfChanged(persistentProject, project, Project::getAuthor, persistentProject::setAuthor);
hasChanged |= applyIfChanged(persistentProject, project, Project::getAuthors, persistentProject::setAuthors);
hasChanged |= applyIfChanged(persistentProject, project, Project::getPublisher, persistentProject::setPublisher);
hasChanged |= applyIfChanged(persistentProject, project, Project::getManufacturer, persistentProject::setManufacturer);
hasChanged |= applyIfChanged(persistentProject, project, Project::getSupplier, persistentProject::setSupplier);
Expand Down Expand Up @@ -406,7 +406,7 @@ private Map<ComponentIdentity, Component> processComponents(
component.setNew(true); // Transient
} else {
persistentComponent.setBomRef(component.getBomRef()); // Transient
applyIfChanged(persistentComponent, component, Component::getAuthor, persistentComponent::setAuthor);
applyIfChanged(persistentComponent, component, Component::getAuthors, persistentComponent::setAuthors);
applyIfChanged(persistentComponent, component, Component::getPublisher, persistentComponent::setPublisher);
applyIfChanged(persistentComponent, component, Component::getSupplier, persistentComponent::setSupplier);
applyIfChanged(persistentComponent, component, Component::getClassifier, persistentComponent::setClassifier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
Expand Down Expand Up @@ -130,6 +131,11 @@ public void exportProjectAsCycloneDxInventoryTest() {
project.setClassifier(Classifier.APPLICATION);
project.setManufacturer(projectManufacturer);
project.setSupplier(projectSupplier);
List<OrganizationalContact> authors = new ArrayList<>();
authors.add(new OrganizationalContact() {{
setName("SampleAuthor");
}});
project.setAuthors(authors);
project = qm.createProject(project, null, false);

final var projectProperty = new ProjectProperty();
Expand Down Expand Up @@ -237,6 +243,7 @@ public void exportProjectAsCycloneDxInventoryTest() {
"component": {
"type": "application",
"bom-ref": "${json-unit.matches:projectUuid}",
"author": "SampleAuthor",
"supplier": {
"name": "projectSupplier"
},
Expand Down
Loading

0 comments on commit c63745b

Please sign in to comment.