Skip to content

Commit

Permalink
feat(rest): create new endpoint for bulk delete function
Browse files Browse the repository at this point in the history
Signed-off-by: Shi Qiu <[email protected]>
  • Loading branch information
shi9qiu committed Dec 27, 2024
1 parent aadf189 commit 351d6a2
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,11 @@ public BulkOperationNode deleteBulkRelease(String releaseId, User user, boolean
Release referencingRelease = workReleaseMap.get(referencingReleaseId);
Map<String, ReleaseRelationship> relationMap = referencingRelease.getReleaseIdToRelationship();
relationMap.remove(leafReleaseId);
if (!isPreview) {
releaseRepository.update(referencingRelease);
//Do not update the repository link if both the referencing Release and the referenced Release are externally referenced.
if (!externalLinkMap.get(referencingReleaseId)) {
if (!isPreview) {
releaseRepository.update(referencingRelease);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import org.eclipse.sw360.datahandler.thrift.*;
import org.eclipse.sw360.datahandler.thrift.components.*;
import org.eclipse.sw360.datahandler.thrift.projects.Project;
import org.eclipse.sw360.datahandler.thrift.projects.ProjectProjectRelationship;
import org.eclipse.sw360.datahandler.thrift.projects.ProjectRelationship;
import org.eclipse.sw360.datahandler.thrift.projects.ProjectType;
import org.eclipse.sw360.datahandler.thrift.users.User;
import org.eclipse.sw360.datahandler.thrift.users.UserGroup;
import org.eclipse.sw360.datahandler.thrift.vendors.Vendor;
Expand All @@ -34,6 +37,10 @@
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.google.common.collect.ImmutableMap;

import java.io.BufferedWriter;
import java.io.FileWriter;
Expand All @@ -48,6 +55,8 @@
@RunWith(MockitoJUnitRunner.class)
public class BulkDeleteUtilTest {

private static final Logger log = LogManager.getLogger(BulkDeleteUtilTest.class);

private static final String dbName = DatabaseSettingsTest.COUCH_DB_DATABASE;
private static final String attachmentsDbName = DatabaseSettingsTest.COUCH_DB_ATTACHMENTS;
private static final String changeLogsDbName = DatabaseSettingsTest.COUCH_DB_CHANGELOGS;
Expand Down Expand Up @@ -154,7 +163,7 @@ public void tearDown() throws Exception {
@Test
public void testGetAllLinkedReleaseMap() throws Exception {
if (!isFeatureEnable()) {
System.out.println("BulkReleaseDeletion is disabled. these test is Skipped.");
log.warn("BulkReleaseDeletion is disabled. these test is Skipped.");
return;
}

Expand Down Expand Up @@ -230,7 +239,7 @@ public void testGetExternalLinkMap() throws Exception {
@Test
public void testDeleteBulkRelease001() throws Exception {
if (!isFeatureEnable()) {
System.out.println("BulkReleaseDeletion is disabled. these test is Skipped.");
log.warn("BulkReleaseDeletion is disabled. these test is Skipped.");
return;
}

Expand Down Expand Up @@ -461,7 +470,7 @@ private void checkBulkOperationNode(BulkOperationNode node, Map<String, Object[]
//@Test
public void testDeleteBulkRelease002() throws Exception {
if (!isFeatureEnable()) {
System.out.println("BulkReleaseDeletion is disabled. these test is Skipped.");
log.warn("BulkReleaseDeletion is disabled. these test is Skipped.");
return;
}

Expand Down Expand Up @@ -517,10 +526,64 @@ public void testDeleteBulkRelease002() throws Exception {
}
}

@Test
public void testDeleteBulkRelease_ExternalLink001() throws Exception {
if (!isFeatureEnable()) {
log.warn("BulkReleaseDeletion is disabled. these test is Skipped.");
return;
}

List<String> releaseIdList = new ArrayList<String>();
List<String> componentIdList = new ArrayList<String>();

createTestRecords002(1, 2, releaseIdList, componentIdList);
String rootReleaseId = releaseIdList.get(0);
assertEquals(3, releaseIdList.size());
assertEquals(3, componentIdList.size());

Project project = new Project().setId("P1").setName("project1").setVisbility(Visibility.EVERYONE).setProjectType(ProjectType.CUSTOMER);
project.putToReleaseIdToUsage(rootReleaseId, new ProjectReleaseRelationship(ReleaseRelationship.CONTAINED, MainlineState.OPEN));
databaseConnector.add(project);

BulkOperationNode level1Component = bulkDeleteUtil.deleteBulkRelease(rootReleaseId, user1, false);
assertNotNull(level1Component);

//Check the BulkOperationNode status
//Object[0] : NodeType, Object[1] : ResultState
Map<String, Object[]> expectedResults = new HashMap<String, Object[]>();
expectedResults.put(releaseIdList.get(0), new Object[]{BulkOperationNodeType.RELEASE, BulkOperationResultState.EXCLUDED});
expectedResults.put(releaseIdList.get(1), new Object[]{BulkOperationNodeType.RELEASE, BulkOperationResultState.EXCLUDED});
expectedResults.put(releaseIdList.get(2), new Object[]{BulkOperationNodeType.RELEASE, BulkOperationResultState.EXCLUDED});
expectedResults.put(componentIdList.get(0), new Object[]{BulkOperationNodeType.COMPONENT, BulkOperationResultState.EXCLUDED});
expectedResults.put(componentIdList.get(1), new Object[]{BulkOperationNodeType.COMPONENT, BulkOperationResultState.EXCLUDED});
expectedResults.put(componentIdList.get(2), new Object[]{BulkOperationNodeType.COMPONENT, BulkOperationResultState.EXCLUDED});
checkBulkOperationNode(level1Component, expectedResults);

//Releases to be undeleted
for (String releaseId : releaseIdList) {
assertTrue(this.releaseExists(releaseId));
}

//Release links to be undeleted
Release release0 = databaseConnector.get(Release.class, releaseIdList.get(0));
assertEquals(1, release0.getReleaseIdToRelationshipSize());
Release release1 = databaseConnector.get(Release.class, releaseIdList.get(1));
assertEquals(1, release1.getReleaseIdToRelationshipSize());
Release release2 = databaseConnector.get(Release.class, releaseIdList.get(2));
assertEquals(0, release2.getReleaseIdToRelationshipSize());

//Components and links to be undeleted
for (String componentId : componentIdList) {
assertTrue(this.componentExists(componentId));
Component component = databaseConnector.get(Component.class, componentId);
assertEquals(1, component.getReleaseIdsSize());
}
}

@Test
public void testDeleteBulkRelease_ConflictError001() throws Exception {
if (!isFeatureEnable()) {
System.out.println("BulkReleaseDeletion is disabled. these test is Skipped.");
log.warn("BulkReleaseDeletion is disabled. these test is Skipped.");
return;
}

Expand Down Expand Up @@ -743,7 +806,7 @@ public void checkDeletedReleaseListInLoop(int loopCount, List<Release> deletedRe
@Test
public void testDeleteBulkRelease_ConflictError002() throws Exception {
if (!isFeatureEnable()) {
System.out.println("BulkReleaseDeletion is disabled. these test is Skipped.");
log.warn("BulkReleaseDeletion is disabled. these test is Skipped.");
return;
}

Expand Down Expand Up @@ -931,7 +994,7 @@ public void checkDeletedReleaseListInLoop(int loopCount, List<Release> deletedRe
@Test
public void testDeleteBulkRelease_ConflictError003() throws Exception {
if (!isFeatureEnable()) {
System.out.println("BulkReleaseDeletion is disabled. these test is Skipped.");
log.warn("BulkReleaseDeletion is disabled. these test is Skipped.");
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public Sw360Module() {
setMixInAnnotation(RestrictedResource.class, Sw360Module.RestrictedResourceMixin.class);
setMixInAnnotation(RestApiToken.class, Sw360Module.RestApiTokenMixin.class);
setMixInAnnotation(ProjectLink.class, Sw360Module.ProjectLinkMixin.class);
setMixInAnnotation(BulkOperationNode.class, Sw360Module.BulkOperationNodeMixin.class);

// Make spring doc aware of the mixin(s)
SpringDocUtils.getConfig()
Expand Down Expand Up @@ -207,6 +208,7 @@ public Sw360Module() {
.replaceWithClass(RestrictedResource.class, RestrictedResourceMixin.class)
.replaceWithClass(RestApiToken.class, Sw360Module.RestApiTokenMixin.class)
.replaceWithClass(ProjectLink.class, ProjectLinkMixin.class)
.replaceWithClass(BulkOperationNode.class, BulkOperationNodeMixin.class)
.replaceWithClass(SPDXDocument.class, Sw360Module.SPDXDocumentMixin.class)
.replaceWithClass(DocumentCreationInformation.class, Sw360Module.DocumentCreationInformationMixin.class)
.replaceWithClass(PackageInformation.class, Sw360Module.PackageInformationMixin.class)
Expand Down Expand Up @@ -2637,5 +2639,22 @@ public abstract static class RestApiTokenMixin extends RestApiToken {
"setTreeLevel",
})
abstract static class ProjectLinkMixin extends ProjectLink {}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(value = {
"setId",
"setName",
"setVersion",
"setType",
"setParentId",
"setChildList",
"childListSize",
"childListIterator",
"setState",
"setAdditionalData",
"additionalDataSize"
})
static abstract class BulkOperationNodeMixin extends BulkOperationNode {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import org.eclipse.sw360.datahandler.thrift.spdx.documentcreationinformation.DocumentCreationInformation;
import org.eclipse.sw360.datahandler.thrift.spdx.spdxdocument.SPDXDocument;
import org.eclipse.sw360.datahandler.thrift.spdx.spdxpackageinfo.PackageInformation;
import org.eclipse.sw360.datahandler.thrift.components.BulkOperationNode;
import org.eclipse.sw360.datahandler.thrift.users.User;
import org.eclipse.sw360.datahandler.thrift.vendors.Vendor;
import org.eclipse.sw360.datahandler.thrift.vulnerabilities.ReleaseVulnerabilityRelation;
Expand Down Expand Up @@ -1768,4 +1769,24 @@ private Set<Attachment> getAttachmentsFromRequest(Object attachmentData, ObjectM
})
.collect(Collectors.toSet());
}

@PreAuthorize("hasAuthority('WRITE')")
@Operation(
summary = "Bulk delete releases.",
description = "Bulk delete existing releases.",
tags = {"Releases"}
)
@DeleteMapping(value = RELEASES_URL + "/{id}/bulkDelete")
public ResponseEntity<BulkOperationNode> bulkDeleteReleases(
@Parameter(description = "The release id to be bulk-deleted.")
@PathVariable("id") String id,
@Parameter(description = "isPreview flag for bulk deletion.")
@RequestParam(value = "isPreview", defaultValue="false", required = false) boolean isPreview
) throws TException {
User user = restControllerHelper.getSw360UserFromAuthentication();
BulkOperationNode result = releaseService.deleteBulkRelease(id, user, isPreview);

return new ResponseEntity<BulkOperationNode>(result, HttpStatus.OK);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,11 @@ public RequestStatus deleteRelease(String releaseId, User sw360User) throws TExc
}
return deleteStatus;
}

public BulkOperationNode deleteBulkRelease(String releaseId, User sw360User, boolean isPreview) throws TException {
ComponentService.Iface sw360ComponentClient = getThriftComponentClient();
return sw360ComponentClient.deleteBulkRelease(releaseId, sw360User, isPreview);
}

public Set<Project> getProjectsByRelease(String releaseId, User sw360User) throws TException {
return projectService.getProjectsByRelease(releaseId, sw360User);
Expand Down

0 comments on commit 351d6a2

Please sign in to comment.