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

feat(rest) : Endpoint for export SBOM at project detail page #2950

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 @@ -138,6 +138,8 @@ public class SW360Constants {
public static final String ADD_LIST_EMAIL = "listEmail";
public static final String DEPARTMENT_KEY = "departmentKey";
public static final String DELETE_LIST_EMAIL = "deleteEmail";
public static final String SBOM = "sbom";


/**
* Hashmap containing the name field for each type.
Expand All @@ -162,6 +164,8 @@ public class SW360Constants {
AttachmentType.COMPONENT_LICENSE_INFO_COMBINED, AttachmentType.INITIAL_SCAN_REPORT);
public static final Collection<AttachmentType> SOURCE_CODE_ATTACHMENT_TYPES = Arrays.asList(AttachmentType.SOURCE, AttachmentType.SOURCE_SELF);
public static final String CONTENT_TYPE_OPENXML_SPREADSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
public static final String CONTENT_TYPE_XML = "application/xml";
public static final String CONTENT_TYPE_JSON = "application/json";

public static final String NOTIFICATION_CLASS_RELEASE = "release";
public static final String NOTIFICATION_CLASS_MODERATION_REQUEST = "moderation";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.eclipse.sw360.datahandler.common.SW360Constants.CONTENT_TYPE_OPENXML_SPREADSHEET;
import static org.eclipse.sw360.datahandler.common.SW360Constants.XML_FILE_EXTENSION;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;

import java.io.IOException;
Expand Down Expand Up @@ -84,7 +85,7 @@ public void getProjectReport(
@Parameter(description = "Module name.", schema = @Schema(allowableValues = {
SW360Constants.PROJECTS, SW360Constants.COMPONENTS, SW360Constants.LICENSES,
LICENSE_INFO, LICENSES_RESOURCE_BUNDLE, SW360Constants.PROJECT_RELEASE_SPREADSHEET_WITH_ECCINFO,
EXPORT_CREATE_PROJ_CLEARING_REPORT
EXPORT_CREATE_PROJ_CLEARING_REPORT,SW360Constants.SBOM
}))
@RequestParam(value = "module", required = true) String module,
@Parameter(description = "Exclude release version from the license info file")
Expand All @@ -101,6 +102,8 @@ public void getProjectReport(
@RequestParam(value = "externalIds", required = false, defaultValue = "") String externalIds,
@Parameter(description = "Generate report for only current project or with Sub projects. Can be supplied with modules [" + LICENSE_INFO + ", " + EXPORT_CREATE_PROJ_CLEARING_REPORT + "]")
@RequestParam(value = "withSubProject", required = false, defaultValue = "false") boolean withSubProject,
@Parameter(description = "Type of SBOM file extention")
@RequestParam(value = "bomType", required = false) String bomType,
HttpServletRequest request,
HttpServletResponse response
) throws TException {
Expand Down Expand Up @@ -139,6 +142,10 @@ public void getProjectReport(
exportProjectCreateClearingRequest(response, sw360User, module, projectId, excludeReleaseVersion,
generatorClassName, variant, template, externalIds);
break;
case SW360Constants.SBOM:
exportSBOM(response, sw360User, module, projectId,generatorClassName,
bomType,withSubProject);
break;
default:
break;
}
Expand Down Expand Up @@ -371,4 +378,28 @@ private String getBaseUrl(HttpServletRequest request) {
String ctx = request.getContextPath();
return url.substring(0, url.length() - uri.length() + ctx.length()) + "/";
}


private void exportSBOM(
HttpServletResponse response, User sw360User, String module, String projectId,
String generatorClassName, String bomType, boolean withSubProject
) throws TException {
try {
String buff = sw360ReportService.getProjectSBOMBuffer(sw360User, projectId,bomType,withSubProject);
response.setContentType(SW360Constants.CONTENT_TYPE_JSON);
String fileName = sw360ReportService.getSBOMFileName(sw360User, projectId, module, bomType);

if (null == buff) {
throw new TException("No data available for the user " + sw360User.getEmail());
}
if(SW360Constants.XML_FILE_EXTENSION.equalsIgnoreCase(bomType)){
response.setContentType(SW360Constants.CONTENT_TYPE_XML);
}
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName));
copyDataStreamToResponse(response, ByteBuffer.wrap(buff.getBytes()));
} catch (Exception e) {
log.error(e);
throw new TException(e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import org.eclipse.sw360.exporter.ReleaseExporter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.eclipse.sw360.datahandler.thrift.RequestSummary;
import org.eclipse.sw360.datahandler.thrift.RequestStatus;

import lombok.RequiredArgsConstructor;

Expand Down Expand Up @@ -437,4 +439,41 @@ public ByteBuffer getProjectReleaseSpreadSheetWithEcc(User user, String projectI
}
return ByteBuffer.wrap(IOUtils.toByteArray(exporter.makeExcelExport(releases)));
}

public String getProjectSBOMBuffer(User user, String projectId, String bomType, boolean withSubProject) throws TException {
String bomString = "";
try {
if (CommonUtils.isNotNullEmptyOrWhitespace(projectId)) {

RequestSummary summary = projectclient.exportCycloneDxSbom(projectId, bomType, withSubProject, user);
RequestStatus status = summary.getRequestStatus();
if (RequestStatus.FAILED_SANITY_CHECK.equals(status)) {
bomString = "{\"status\": \"" + status.name() + "\"}";
} else if (RequestStatus.ACCESS_DENIED.equals(status)) {
bomString = "{\"status\": \"" + status.name() + "\", \"message\": \"" + SW360Constants.SBOM_IMPORT_EXPORT_ACCESS_USER_ROLE + "\"}";
} else if (RequestStatus.FAILURE.equals(status)) {
bomString = "{\"status\": \"" + status.name() + "\", \"message\": \"" + summary.getMessage() + "\"}";
} else {
Comment on lines +450 to +456
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These states should cause an exception and not return a JSON with a normal 200 response code. Please throw appropriate exceptions based on the failure state.

Otherwise, as of now, I will get a JSON saying {"status": "ACCESS_DENIED", "message": "..."} and will assume it is a CDX SBOM unless I open it.

bomString = summary.getMessage();
}
}
} catch (TException e) {
log.error("An error occured while generating SBOM file for export.", e);
}
return bomString;
}

public String getSBOMFileName(User user, String projectId, String module, String bomType) throws TException {
String documentName = "";
if(projectId != null && !projectId.equalsIgnoreCase("null")) {
Project project = projectclient.getProjectById(projectId, user);
documentName = String.format("project_%s(%s)_%s.xml", project.getName(), project.getVersion(),
SW360Utils.getCreatedOnTime(), "_SBOM");
if(SW360Constants.JSON_FILE_EXTENSION.equalsIgnoreCase(bomType)){
documentName = String.format("project_%s(%s)_%s.json", project.getName(), project.getVersion(),
SW360Utils.getCreatedOnTime(), "_SBOM");
}
}
return documentName;
}
}