Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project cloning logic for cloning policy violations and Violationanalysis #3248

Merged
merged 1 commit into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,33 @@ public synchronized PolicyViolation addPolicyViolationIfNotExist(final PolicyVio
return result;
}

/**
* clones a policy violation
* @param sourcePolicyViolation the policy violation to clone
* @param destinationComponent the corresponding component
*/
public PolicyViolation clonePolicyViolation(PolicyViolation sourcePolicyViolation, Component destinationComponent){
//cloning PolicyViolation
final PolicyViolation policyViolation = new PolicyViolation();
policyViolation.setType(sourcePolicyViolation.getType());
policyViolation.setComponent(destinationComponent);
policyViolation.setPolicyCondition(sourcePolicyViolation.getPolicyCondition());
policyViolation.setTimestamp(sourcePolicyViolation.getTimestamp());
policyViolation.setText(sourcePolicyViolation.getText());
policyViolation.setType(sourcePolicyViolation.getType());
//cloning ViolatioAnalysis
ViolationAnalysis violationAnalysis = cloneViolationAnalysis(destinationComponent, sourcePolicyViolation);
//cloning ViolationAnalysisComments
List<ViolationAnalysisComment> comments = cloneViolationAnalysisComments(sourcePolicyViolation, violationAnalysis);
if(comments != null){
violationAnalysis.setAnalysisComments(comments);
}
policyViolation.setAnalysis(violationAnalysis);
policyViolation.getAnalysis().setPolicyViolation(policyViolation);
policyViolation.setUuid(sourcePolicyViolation.getUuid());
return policyViolation;
}

/**
* Returns a List of all Policy objects.
* This method if designed NOT to provide paginated results.
Expand Down Expand Up @@ -340,6 +367,24 @@ public PaginatedResult getPolicyViolations(boolean includeSuppressed) {
return result;
}

/**
* clones a ViolationAnalysis
* @param destinationComponent the destinationComponent
* @param sourcePolicyViolation the PolicyViolation to clone from
* @return the cloned violationAnalysis
*/
public ViolationAnalysis cloneViolationAnalysis(Component destinationComponent, PolicyViolation sourcePolicyViolation){
ViolationAnalysis violationAnalysis = new ViolationAnalysis();
violationAnalysis.setComponent(destinationComponent);
if(sourcePolicyViolation.getAnalysis() != null){
violationAnalysis.setSuppressed(sourcePolicyViolation.getAnalysis().isSuppressed());
violationAnalysis.setViolationAnalysisState(sourcePolicyViolation.getAnalysis().getAnalysisState());
} else {
violationAnalysis.setViolationAnalysisState(ViolationAnalysisState.NOT_SET);
}
return violationAnalysis;
}

/**
* Returns a ViolationAnalysis for the specified Component and PolicyViolation.
* @param component the Component
Expand Down Expand Up @@ -378,6 +423,28 @@ public ViolationAnalysis makeViolationAnalysis(Component component, PolicyViolat
return getViolationAnalysis(violationAnalysis.getComponent(), violationAnalysis.getPolicyViolation());
}

/**
* clones ViolationAnalysisComments
* @param sourcePolicyViolation the source PolicyViolation
* @param violationAnalysis the ViolationAnalysis to clone from
* @return the cloned ViolationAnalysisComments
*/
public List<ViolationAnalysisComment> cloneViolationAnalysisComments(PolicyViolation sourcePolicyViolation, ViolationAnalysis violationAnalysis){
List<ViolationAnalysisComment> comments = new ArrayList<ViolationAnalysisComment>();
if(sourcePolicyViolation.getAnalysis() != null && sourcePolicyViolation.getAnalysis().getAnalysisComments() != null){
for(ViolationAnalysisComment c : sourcePolicyViolation.getAnalysis().getAnalysisComments()){
ViolationAnalysisComment comment = new ViolationAnalysisComment();
comment.setViolationAnalysis(violationAnalysis);
comment.setComment(c.getComment());
comment.setCommenter(c.getCommenter());
comment.setTimestamp(c.getTimestamp());
comments.add(comment);
}
}

return comments;
}

/**
* Adds a new violation analysis comment to the specified violation analysis.
* @param violationAnalysis the violation analysis object to add a comment to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.dependencytrack.model.Component;
import org.dependencytrack.model.ConfigPropertyConstants;
import org.dependencytrack.model.FindingAttribution;
import org.dependencytrack.model.PolicyViolation;
import org.dependencytrack.model.Project;
import org.dependencytrack.model.ProjectMetadata;
import org.dependencytrack.model.ProjectProperty;
Expand Down Expand Up @@ -568,7 +569,7 @@ public Project updateProject(Project transientProject, boolean commitIndex) {
@Override
public Project clone(UUID from, String newVersion, boolean includeTags, boolean includeProperties,
boolean includeComponents, boolean includeServices, boolean includeAuditHistory,
boolean includeACL) {
boolean includeACL, boolean includePolicyViolations) {
final Project source = getObjectByUuid(Project.class, from, Project.FetchGroup.ALL.name());
if (source == null) {
LOGGER.warn("Project with UUID %s was supposed to be cloned, but it does not exist anymore".formatted(from));
Expand Down Expand Up @@ -694,6 +695,19 @@ public Project clone(UUID from, String newVersion, boolean includeTags, boolean
}
}


if(includeComponents && includePolicyViolations){
final List<PolicyViolation> sourcePolicyViolations = getAllPolicyViolations(source);
if(sourcePolicyViolations != null){
for(final PolicyViolation policyViolation: sourcePolicyViolations){
final Component destinationComponent = clonedComponents.get(policyViolation.getComponent().getId());
final PolicyViolation clonedPolicyViolation = clonePolicyViolation(policyViolation, destinationComponent);
persist(clonedPolicyViolation);
}
}
}


project = getObjectById(Project.class, project.getId());
Event.dispatch(new IndexEvent(IndexEvent.Action.CREATE, project));
commitSearchIndex(true, Project.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,9 +440,9 @@ public boolean updateNewProjectACL(Project transientProject, Principal principal

public Project clone(UUID from, String newVersion, boolean includeTags, boolean includeProperties,
boolean includeComponents, boolean includeServices, boolean includeAuditHistory,
boolean includeACL) {
boolean includeACL, boolean includePolicyViolations) {
return getProjectQueryManager().clone(from, newVersion, includeTags, includeProperties,
includeComponents, includeServices, includeAuditHistory, includeACL);
includeComponents, includeServices, includeAuditHistory, includeACL, includePolicyViolations);
}

public Project updateLastBomImport(Project p, Date date, String bomFormat) {
Expand Down Expand Up @@ -609,6 +609,10 @@ public synchronized PolicyViolation addPolicyViolationIfNotExist(final PolicyVio
return getPolicyQueryManager().addPolicyViolationIfNotExist(pv);
}

public PolicyViolation clonePolicyViolation(PolicyViolation sourcePolicyViolation, Component destinationComponent){
return getPolicyQueryManager().clonePolicyViolation(sourcePolicyViolation, destinationComponent);
}

public List<PolicyViolation> getAllPolicyViolations() {
return getPolicyQueryManager().getAllPolicyViolations();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public class CloneProjectRequest {

private final boolean includeACL;

private final boolean includePolicyViolations;

@JsonCreator
public CloneProjectRequest(@JsonProperty(value = "project", required = true) String project,
@JsonProperty(value = "version", required = true) String version,
Expand All @@ -68,7 +70,8 @@ public CloneProjectRequest(@JsonProperty(value = "project", required = true) Str
@JsonProperty(value = "includeComponents") boolean includeComponents,
@JsonProperty(value = "includeServices") boolean includeServices,
@JsonProperty(value = "includeAuditHistory") boolean includeAuditHistory,
@JsonProperty(value = "includeACL") boolean includeACL) {
@JsonProperty(value = "includeACL") boolean includeACL,
@JsonProperty(value = "includePolicyViolations") boolean includePolicyViolations) {
if (includeDependencies) { // For backward compatibility
includeComponents = true;
}
Expand All @@ -81,6 +84,7 @@ public CloneProjectRequest(@JsonProperty(value = "project", required = true) Str
this.includeServices = includeServices;
this.includeAuditHistory = includeAuditHistory;
this.includeACL = includeACL;
this.includePolicyViolations = includePolicyViolations;
}

public String getProject() {
Expand Down Expand Up @@ -119,4 +123,8 @@ public boolean includeACL() {
return includeACL;
}

public boolean includePolicyViolations() {
return includePolicyViolations;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void inform(final Event e) {
try (QueryManager qm = new QueryManager()) {
final Project project = qm.clone(UUID.fromString(request.getProject()),
request.getVersion(), request.includeTags(), request.includeProperties(),
request.includeComponents(), request.includeServices(), request.includeAuditHistory(), request.includeACL());
request.includeComponents(), request.includeServices(), request.includeAuditHistory(), request.includeACL(), request.includePolicyViolations());
LOGGER.info("Cloned project: " + request.getProject() + " to " + project.getUuid());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class CloneProjectEventTest {
@Test
public void testEvent() {
UUID uuid = UUID.randomUUID();
CloneProjectRequest request = new CloneProjectRequest(uuid.toString(), "1.0", true, true, true, true, true, true, true);
CloneProjectRequest request = new CloneProjectRequest(uuid.toString(), "1.0", true, true, true, true, true, true, true, true);
CloneProjectEvent event = new CloneProjectEvent(request);
Assert.assertEquals(request, event.getRequest());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,32 @@
package org.dependencytrack.persistence;

import org.dependencytrack.PersistenceCapableTest;
import org.dependencytrack.model.Classifier;
import org.dependencytrack.model.Component;
import org.dependencytrack.model.Policy;
import org.dependencytrack.model.PolicyViolation;
import org.dependencytrack.model.Project;
import org.dependencytrack.model.ViolationAnalysis;
import org.dependencytrack.model.ViolationAnalysisComment;
import org.dependencytrack.model.ViolationAnalysisState;
import org.junit.Test;
import org.junit.Assert;

import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;

import ch.qos.logback.core.subst.Token.Type;
import us.springett.parsers.cpe.Cpe;
import us.springett.parsers.cpe.CpeParser;
import us.springett.parsers.cpe.exceptions.CpeParsingException;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;

import static java.util.Collections.newSetFromMap;
import static org.assertj.core.api.Assertions.assertThat;

public class PolicyQueryManagerTest extends PersistenceCapableTest {
Expand All @@ -47,4 +67,53 @@ public void testRemoveProjectFromPolicies() {
assertThat(qm.getObjectById(Policy.class, policy2.getId()).getProjects()).isEmpty();
}

@Test
public void testclonePolicyViolation() throws Exception{
PolicyViolation policyViolation = new PolicyViolation();
policyViolation.setId(1);

// Component for cloning
Component component = new Component();
component.setId(111L);
component.setName("name");
component.setVersion("1.0");
component.setCopyright("Copyright Acme");

policyViolation.setComponent(component);
policyViolation.setText("policyViolation");
policyViolation.setTimestamp(new Date());
policyViolation.setType(PolicyViolation.Type.LICENSE);

// ViolationAnalysis for cloning
ViolationAnalysis violationAnalysis = new ViolationAnalysis();
violationAnalysis.setSuppressed(true);
violationAnalysis.setViolationAnalysisState(ViolationAnalysisState.APPROVED);

// ViolationAnalysisComments
List<ViolationAnalysisComment> violationAnalysisComments = new ArrayList<>();
ViolationAnalysisComment violationAnalysisComment = new ViolationAnalysisComment();
violationAnalysisComment.setComment("testComment");
violationAnalysisComment.setCommenter("admin");
violationAnalysisComment.setTimestamp(new Date());
violationAnalysisComment.setViolationAnalysis(violationAnalysis);
violationAnalysisComments.add(violationAnalysisComment);
violationAnalysis.setAnalysisComments(violationAnalysisComments);

policyViolation.setAnalysis(violationAnalysis);

PolicyViolation clonedPolicyViolation = qm.clonePolicyViolation(policyViolation, component);
Assert.assertEquals(policyViolation.getText(), clonedPolicyViolation.getText());
Assert.assertEquals(policyViolation.getType(), clonedPolicyViolation.getType());
Assert.assertEquals(policyViolation.getTimestamp(), clonedPolicyViolation.getTimestamp());
Assert.assertEquals(policyViolation.getAnalysis().isSuppressed(), clonedPolicyViolation.getAnalysis().isSuppressed());
Assert.assertEquals(policyViolation.getAnalysis().getAnalysisState(), clonedPolicyViolation.getAnalysis().getAnalysisState());
Assert.assertEquals(policyViolation.getAnalysis().getAnalysisComments().get(0).getComment(), clonedPolicyViolation.getAnalysis().getAnalysisComments().get(0).getComment());
Assert.assertEquals(policyViolation.getAnalysis().getAnalysisComments().get(0).getCommenter(), clonedPolicyViolation.getAnalysis().getAnalysisComments().get(0).getCommenter());
Assert.assertEquals(policyViolation.getAnalysis().getAnalysisComments().get(0).getTimestamp(), clonedPolicyViolation.getAnalysis().getAnalysisComments().get(0).getTimestamp());
Assert.assertEquals(policyViolation.getComponent().getId(), clonedPolicyViolation.getComponent().getId());
Assert.assertEquals(policyViolation.getComponent().getName(), clonedPolicyViolation.getComponent().getName());
Assert.assertEquals(policyViolation.getComponent().getCopyright(), clonedPolicyViolation.getComponent().getCopyright());
Assert.assertEquals(policyViolation.getComponent().getVersion(), clonedPolicyViolation.getComponent().getVersion());
}

}