diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java index b5948ebc9a..97675bcab2 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ComponentDatabaseHandler.java @@ -54,9 +54,12 @@ import org.eclipse.sw360.datahandler.thrift.vulnerabilities.ReleaseVulnerabilityRelation; import org.eclipse.sw360.datahandler.thrift.vulnerabilities.VulnerabilityCheckStatus; import org.eclipse.sw360.datahandler.thrift.vulnerabilities.VulnerabilityService; +import org.eclipse.sw360.exporter.ComponentExporter; +import org.eclipse.sw360.exporter.ProjectExporter; import org.eclipse.sw360.mail.MailConstants; import org.eclipse.sw360.mail.MailUtil; import org.apache.logging.log4j.Logger; +import org.apache.commons.io.IOUtils; import org.apache.http.HttpStatus; import org.apache.logging.log4j.LogManager; import org.apache.thrift.TException; @@ -69,6 +72,7 @@ import org.spdx.library.InvalidSPDXAnalysisException; import java.io.InputStreamReader; import java.net.MalformedURLException; +import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -2832,4 +2836,44 @@ public Map getReleasesName(String releases) { } return releaseNames; } + + public String getComponentReportInEmail(User user,boolean extendedByReleases) throws TException { + try { + List componentlist = getRecentComponentsSummary(-1, user); + ComponentExporter exporter = getComponentExporterObject(componentlist,user, extendedByReleases); + return exporter.makeExcelExportForProject(componentlist, user); + }catch (IOException e) { + throw new SW360Exception(e.getMessage()); + } + } + + private ComponentExporter getComponentExporterObject(List componentList ,User user, + boolean extendedByRelease) throws SW360Exception { + ThriftClients thriftClients = new ThriftClients(); + return new ComponentExporter(thriftClients.makeComponentClient(), componentList, user,extendedByRelease); + } + + public ByteBuffer downloadExcel(User user,boolean extendedByReleases,String token) throws SW360Exception { + try { + ThriftClients thriftClients = new ThriftClients(); + ComponentExporter exporter = new ComponentExporter(thriftClients.makeComponentClient(), user, + extendedByReleases); + InputStream stream = exporter.downloadExcelSheet(token); + return ByteBuffer.wrap(IOUtils.toByteArray(stream)); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public ByteBuffer getComponentReportDataStream(User user, boolean extendedByReleases) throws TException{ + try { + List componentlist = getRecentComponentsSummary(-1, user); + ComponentExporter exporter = getComponentExporterObject(componentlist, user, extendedByReleases); + InputStream stream = exporter.makeExcelExport(componentlist); + return ByteBuffer.wrap(IOUtils.toByteArray(stream)); + }catch (IOException e) { + throw new SW360Exception(e.getMessage()); + } + } } diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectDatabaseHandler.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectDatabaseHandler.java index 232aa8ee53..cec9696cc4 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectDatabaseHandler.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectDatabaseHandler.java @@ -73,6 +73,9 @@ import static org.eclipse.sw360.datahandler.common.SW360Utils.printName; import static org.eclipse.sw360.datahandler.common.WrappedException.wrapTException; import static org.eclipse.sw360.datahandler.permissions.PermissionUtils.makePermission; +import org.apache.commons.io.IOUtils; +import org.eclipse.sw360.exporter.ProjectExporter; +import java.nio.ByteBuffer; /** * Class for accessing the CouchDB database @@ -85,6 +88,7 @@ */ public class ProjectDatabaseHandler extends AttachmentAwareDatabaseHandler { + private static final String PROJECTS = "projects"; private static final Logger log = LogManager.getLogger(ProjectDatabaseHandler.class); private static final int DELETION_SANITY_CHECK_THRESHOLD = 5; private static final String DUMMY_NEW_PROJECT_ID = "newproject"; @@ -1907,4 +1911,44 @@ public ProjectData searchByTag(String tag, User user) { public ProjectData searchByType(String type, User user) { return repository.searchByType(type, user); } + + public ByteBuffer getReportDataStream(User user, boolean extendedByReleases) throws TException { + try { + List documents = getAccessibleProjectsSummary(user); + ProjectExporter exporter = getProjectExporterObject(documents, user, extendedByReleases); + InputStream stream = exporter.makeExcelExport(documents); + return ByteBuffer.wrap(IOUtils.toByteArray(stream)); + }catch (IOException e) { + throw new SW360Exception(e.getMessage()); + } + } + + private ProjectExporter getProjectExporterObject(List documents, User user, boolean extendedByReleases) throws SW360Exception { + ThriftClients thriftClients = new ThriftClients(); + return new ProjectExporter(thriftClients.makeComponentClient(), + thriftClients.makeProjectClient(), user, documents, extendedByReleases); + } + + public String getReportInEmail(User user, + boolean extendedByReleases) throws TException { + try { + List documents = getAccessibleProjectsSummary(user); + ProjectExporter exporter = getProjectExporterObject(documents, user, extendedByReleases); + return exporter.makeExcelExportForProject(documents, user); + }catch (IOException e) { + throw new SW360Exception(e.getMessage()); + } + } + + public ByteBuffer downloadExcel(User user, boolean extendedByReleases, String token) throws SW360Exception { + ThriftClients thriftClients = new ThriftClients(); + ProjectExporter exporter = new ProjectExporter(thriftClients.makeComponentClient(), + thriftClients.makeProjectClient(), user, extendedByReleases); + try { + InputStream stream = exporter.downloadExcelSheet(token); + return ByteBuffer.wrap(IOUtils.toByteArray(stream)); + } catch (IOException e) { + throw new SW360Exception(e.getMessage()); + } + } } diff --git a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectRepository.java b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectRepository.java index e4129f4a48..3a98ab671b 100644 --- a/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectRepository.java +++ b/backend/src-common/src/main/java/org/eclipse/sw360/datahandler/db/ProjectRepository.java @@ -10,6 +10,7 @@ */ package org.eclipse.sw360.datahandler.db; +import org.apache.thrift.TException; import org.eclipse.sw360.components.summary.ProjectSummary; import org.eclipse.sw360.components.summary.SummaryType; import org.eclipse.sw360.datahandler.cloudantclient.DatabaseConnectorCloudant; @@ -19,8 +20,10 @@ import org.eclipse.sw360.datahandler.permissions.PermissionUtils; import org.eclipse.sw360.datahandler.permissions.ProjectPermissions; import org.eclipse.sw360.datahandler.thrift.PaginationData; +import org.eclipse.sw360.datahandler.thrift.ThriftClients; import org.eclipse.sw360.datahandler.thrift.projects.Project; import org.eclipse.sw360.datahandler.thrift.projects.ProjectData; +import org.eclipse.sw360.datahandler.thrift.projects.ProjectService; import org.eclipse.sw360.datahandler.thrift.users.User; import org.eclipse.sw360.datahandler.thrift.users.UserGroup; import org.jetbrains.annotations.NotNull; diff --git a/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java b/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java index d311df8c59..3cd038d6b5 100644 --- a/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java +++ b/backend/src/src-components/src/main/java/org/eclipse/sw360/components/ComponentHandler.java @@ -26,6 +26,7 @@ import com.cloudant.client.api.CloudantClient; import java.io.IOException; +import java.nio.ByteBuffer; import java.util.List; import java.util.Map; import java.util.Set; @@ -717,4 +718,19 @@ public Map> getRecentComponentsSummaryWithPagina public void sendExportSpreadsheetSuccessMail(String url, String recepient) throws TException { handler.sendExportSpreadsheetSuccessMail(url, recepient); } + + @Override + public ByteBuffer downloadExcel(User user, boolean extendedByReleases, String token) throws TException { + return handler.downloadExcel(user,extendedByReleases,token); + } + + @Override + public ByteBuffer getComponentReportDataStream(User user, boolean extendedByReleases) throws TException { + return handler.getComponentReportDataStream(user,extendedByReleases); + } + + @Override + public String getComponentReportInEmail(User user, boolean extendedByReleases) throws TException { + return handler.getComponentReportInEmail(user,extendedByReleases); + } } diff --git a/backend/src/src-projects/src/main/java/org/eclipse/sw360/projects/ProjectHandler.java b/backend/src/src-projects/src/main/java/org/eclipse/sw360/projects/ProjectHandler.java index 0a849eb005..4ef086eecd 100644 --- a/backend/src/src-projects/src/main/java/org/eclipse/sw360/projects/ProjectHandler.java +++ b/backend/src/src-projects/src/main/java/org/eclipse/sw360/projects/ProjectHandler.java @@ -43,6 +43,7 @@ import java.util.function.Supplier; import static org.eclipse.sw360.datahandler.common.SW360Assert.*; +import java.nio.ByteBuffer; /** * Implementation of the Thrift service @@ -462,4 +463,22 @@ public int getMyAccessibleProjectCounts(User user) throws TException { public void sendExportSpreadsheetSuccessMail(String url, String recepient) throws TException { handler.sendExportSpreadsheetSuccessMail(url, recepient); } + + @Override + public ByteBuffer downloadExcel(User user, boolean extendedByReleases, String token) + throws TException { + return handler.downloadExcel(user, extendedByReleases,token); + } + + @Override + public ByteBuffer getReportDataStream(User user, boolean extendedByReleases) + throws TException { + return handler.getReportDataStream(user, extendedByReleases); + } + + @Override + public String getReportInEmail(User user, boolean extendedByReleases) + throws TException { + return handler.getReportInEmail(user, extendedByReleases); + } } diff --git a/libraries/datahandler/src/main/thrift/components.thrift b/libraries/datahandler/src/main/thrift/components.thrift index ed264a1a0c..893a191001 100644 --- a/libraries/datahandler/src/main/thrift/components.thrift +++ b/libraries/datahandler/src/main/thrift/components.thrift @@ -909,4 +909,16 @@ service ComponentService { * Send email to the user once spreadsheet export completed */ void sendExportSpreadsheetSuccessMail(1: string url, 2: string userEmail); + /* + * download api + */ + binary downloadExcel(1:User user,2:bool extendedByReleases,3:string token) throws (1: SW360Exception exp); + /* + * get report data stream + */ + binary getComponentReportDataStream(1: User user, 2: bool extendedByReleases) throws (1: SW360Exception exp); + /* + * get component report in mail + */ + string getComponentReportInEmail(1: User user, 2: bool extendedByReleases) throws (1: SW360Exception exp); } diff --git a/libraries/datahandler/src/main/thrift/projects.thrift b/libraries/datahandler/src/main/thrift/projects.thrift index bd5a5e3a78..5950f08464 100644 --- a/libraries/datahandler/src/main/thrift/projects.thrift +++ b/libraries/datahandler/src/main/thrift/projects.thrift @@ -530,4 +530,16 @@ service ProjectService { * Send email to the user once spreadsheet export completed */ void sendExportSpreadsheetSuccessMail(1: string url, 2: string userEmail); + /* + * make excel export + */ + binary getReportDataStream(1: User user,2: bool extendedByReleases) throws (1: SW360Exception exp); + /* + * excel export - return the filepath + */ + string getReportInEmail(1: User user, 2: bool extendedByReleases) throws (1: SW360Exception exp); + /* + * download excel + */ + binary downloadExcel(1:User user,2:bool extendedByReleases,3:string token) throws (1: SW360Exception exc); } diff --git a/rest/resource-server/src/docs/asciidoc/components.adoc b/rest/resource-server/src/docs/asciidoc/components.adoc index e8d93fd077..cf9aaf833b 100644 --- a/rest/resource-server/src/docs/asciidoc/components.adoc +++ b/rest/resource-server/src/docs/asciidoc/components.adoc @@ -375,6 +375,7 @@ include::{snippets}/should_document_get_mycomponents_components/http-response.ad ===== Links include::{snippets}/should_document_get_mycomponents_components/links.adoc[] +<<<<<<< HEAD [[resources-component-get-component-vulnerabilities]] ==== Listing component vulnerabilities @@ -491,3 +492,34 @@ include::{snippets}/should_document_import_sbom_for_component/curl-request.adoc[ ===== Example response include::{snippets}/should_document_import_sbom_for_component/http-response.adoc[] + +[[resources-components-download-report]] +==== Downloading component report + +A `GET` request help to download the components report. + +===== Request parameter +include::{snippets}/should_document_get_component_report/request-parameters.adoc[] + +===== Example request +include::{snippets}/should_document_get_component_report/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_get_component_report/http-response.adoc[] + +[[resources-components-download-report-mail_req]] +==== Downloading component report with mail request + +A `GET` request help to download the components report with mail request. + +===== Request parameter +include::{snippets}/should_document_get_component_report_with_mail_req/request-parameters.adoc[] + +===== Response structure +include::{snippets}/should_document_get_component_report_with_mail_req/response-fields.adoc[] + +===== Example request +include::{snippets}/should_document_get_component_report_with_mail_req/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_get_component_report_with_mail_req/http-response.adoc[] diff --git a/rest/resource-server/src/docs/asciidoc/projects.adoc b/rest/resource-server/src/docs/asciidoc/projects.adoc index fcbfe3d862..6f93810f29 100644 --- a/rest/resource-server/src/docs/asciidoc/projects.adoc +++ b/rest/resource-server/src/docs/asciidoc/projects.adoc @@ -677,4 +677,35 @@ include::{snippets}/should_document_create_summary_administration/response-field include::{snippets}/should_document_create_summary_administration/curl-request.adoc[] ===== Example response -include::{snippets}/should_document_create_summary_administration/http-response.adoc[] \ No newline at end of file +include::{snippets}/should_document_create_summary_administration/http-response.adoc[] + +[[resources-projects-download-report]] +==== Downloading project report + +A `GET` request help to download the projects report with mail request false. + +===== Request parameter +include::{snippets}/should_document_get_project_report_without_mail_req/request-parameters.adoc[] + +===== Example request +include::{snippets}/should_document_get_project_report_without_mail_req/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_get_project_report_without_mail_req/http-response.adoc[] + +[[resources-projects-download-report-mail-request]] +==== Downloading project report with mail request + +A `GET` request help to download the projects report with mail request true. + +===== Request parameter +include::{snippets}/should_document_get_project_report/request-parameters.adoc[] + +===== Response structure +include::{snippets}/should_document_get_project_report/response-fields.adoc[] + +===== Example request +include::{snippets}/should_document_get_project_report/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_get_project_report/http-response.adoc[] diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/report/SW360ReportController.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/report/SW360ReportController.java new file mode 100644 index 0000000000..9eb79045a6 --- /dev/null +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/report/SW360ReportController.java @@ -0,0 +1,216 @@ +/* +SPDX-FileCopyrightText: © 2023 Siemens AG +SPDX-License-Identifier: EPL-2.0 +*/ + +package org.eclipse.sw360.rest.resourceserver.report; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; + +import java.io.IOException; +import java.net.URL; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nonnull; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.thrift.TException; +import org.eclipse.sw360.datahandler.common.CommonUtils; +import org.eclipse.sw360.datahandler.common.SW360Utils; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.rest.resourceserver.core.RestControllerHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.rest.webmvc.BasePathAwareController; +import org.springframework.data.rest.webmvc.RepositoryLinksResource; +import org.springframework.hateoas.server.RepresentationModelProcessor; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import com.google.gson.JsonObject; + +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@BasePathAwareController +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class SW360ReportController implements RepresentationModelProcessor{ + private static final String COMPONENTS = "components"; + + private static final String PROJECTS = "projects"; + + public static final String REPORTS_URL = "/reports"; + + private static String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + + @NonNull + private final RestControllerHelper restControllerHelper; + + @NonNull + private final SW360ReportService sw360ReportService; + + @Override + public RepositoryLinksResource process(RepositoryLinksResource resource) { + resource.add(linkTo(SW360ReportController.class).slash("api/" + REPORTS_URL).withRel("reports")); + return resource; + } + + private List mimeTypeList = Arrays.asList("xls","xlsx"); + + @RequestMapping(value = REPORTS_URL , method = RequestMethod.GET) + public void getProjectReport(@RequestParam(value = "withlinkedreleases", required = false, defaultValue = "false") boolean withLinkedReleases, + @RequestParam(value = "mimetype", required = false, defaultValue = "xlsx") String mimeType, + @RequestParam(value = "mailrequest", required = false, defaultValue="false") boolean mailRequest, + @RequestParam(value = "module", required = true) String module,HttpServletRequest request, + HttpServletResponse response) throws TException{ + + final User sw360User = restControllerHelper.getSw360UserFromAuthentication(); + try { + if(validateMimeType(mimeType)) { + switch (module) { + case PROJECTS : + getProjectReports(withLinkedReleases, mailRequest, response, request,sw360User,module); + break; + + case COMPONENTS : + getComponentsReports(withLinkedReleases,mailRequest, response, request, sw360User,module); + break; + default: + break; + } + } else { + throw new TException("Error : Mimetype either should be : xls/xlsx"); + } + }catch (Exception e) { + throw new TException(e.getMessage()); + } + } + + private void getProjectReports(boolean withLinkedReleases, boolean mailRequest, HttpServletResponse response,HttpServletRequest request, + User sw360User, String module) throws TException{ + try { + if(mailRequest) { + String base = getBaseUrl(request); + + String projectPath = sw360ReportService.getUploadedProjectPath(sw360User, withLinkedReleases); + + String backendURL = base + "api/reports/download?user="+sw360User.getEmail() + "&module=projects" +"&extendedByReleases="+withLinkedReleases+"&token="; + URL emailURL = new URL(backendURL+projectPath); + + if(!CommonUtils.isNullEmptyOrWhitespace(projectPath)) { + sw360ReportService.sendExportSpreadsheetSuccessMail(emailURL.toString(), sw360User.getEmail()); + } + JsonObject responseJson = new JsonObject(); + responseJson.addProperty("response", "E-mail sent succesfully to the end user."); + responseJson.addProperty("url", emailURL.toString()); + responseJson.toString(); + response.getWriter().write(responseJson.toString()); + }else { + downloadExcelReport(withLinkedReleases, response, sw360User,module); + } + }catch (Exception e) { + throw new TException(e.getMessage()); + } + } + + private String getBaseUrl(HttpServletRequest request) { + StringBuffer url = request.getRequestURL(); + String uri = request.getRequestURI(); + String ctx = request.getContextPath(); + return url.substring(0, url.length() - uri.length() + ctx.length()) + "/"; + } + + private void getComponentsReports(boolean withLinkedReleases, boolean mailRequest, HttpServletResponse response, + HttpServletRequest request, User sw360User, String module) throws TException{ + try { + if (mailRequest) { + String base = getBaseUrl(request); + String componentPath = sw360ReportService.getUploadedComponentPath(sw360User,withLinkedReleases); + String backendURL =base + "api/reports/download?user=" + sw360User.getEmail()+ "&module=components" + "&extendedByReleases=" + withLinkedReleases + "&token="; + URL emailURL = new URL(backendURL+componentPath); + + if (!CommonUtils.isNullEmptyOrWhitespace(componentPath)) { + sw360ReportService.sendComponentExportSpreadsheetSuccessMail(emailURL.toString(), sw360User.getEmail()); + } + JsonObject responseJson = new JsonObject(); + responseJson.addProperty("response", "E-mail sent succesfully to the end user."); + responseJson.addProperty("url", emailURL.toString()); + responseJson.toString(); + response.getWriter().write(responseJson.toString()); + } else { + downloadExcelReport(withLinkedReleases, response, sw360User,module); + } + }catch (Exception e) { + throw new TException(e.getMessage()); + } + } + + private void downloadExcelReport(boolean withLinkedReleases, HttpServletResponse response, + User user,String module) throws TException, IOException { + try { + ByteBuffer buffer = null; + switch (module) { + case PROJECTS: + buffer = sw360ReportService.getProjectBuffer(user,withLinkedReleases); + break; + case COMPONENTS: + buffer = sw360ReportService.getComponentBuffer(user,withLinkedReleases); + break; + default: + break; + } + if(null==buffer) { + throw new TException("No data available for the user "+ user.getEmail()); + } + response.setContentType(CONTENT_TYPE); + String filename = String.format("projects-%s.xlsx", SW360Utils.getCreatedOn()); + response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", filename)); + copyDataStreamToResponse(response, buffer); + }catch(Exception e) { + throw new TException(e.getMessage()); + } + } + + private void copyDataStreamToResponse(HttpServletResponse response, ByteBuffer buffer) throws IOException { + FileCopyUtils.copy(buffer.array(), response.getOutputStream()); + } + + private boolean validateMimeType(String mimeType) { + return mimeTypeList.contains(mimeType); + } + + @RequestMapping(value = REPORTS_URL + "/download", method = RequestMethod.GET) + public void downloadExcel(HttpServletRequest request,HttpServletResponse response) throws TException{ + final User sw360User = restControllerHelper.getSw360UserFromAuthentication(); + String module = request.getParameter("module"); + String token = request.getParameter("token"); + String extendedByReleases = request.getParameter("extendedByReleases"); + User user=restControllerHelper.getUserByEmail(sw360User.getEmail()); + String fileConstant="projects-%s.xlsx"; + try { + ByteBuffer buffer = null; + switch (module) { + case PROJECTS: + buffer = sw360ReportService.getReportStreamFromURl(user,Boolean.valueOf(extendedByReleases), token); + break; + case COMPONENTS: + fileConstant="components-%s.xlsx"; + buffer = sw360ReportService.getComponentReportStreamFromURl(user, Boolean.valueOf(extendedByReleases), token); + break; + default: + break; + } + String filename = String.format(fileConstant, SW360Utils.getCreatedOn()); + response.setContentType(CONTENT_TYPE); + response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", filename)); + copyDataStreamToResponse(response, buffer); + } catch (Exception e) { + throw new TException(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/report/SW360ReportService.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/report/SW360ReportService.java new file mode 100644 index 0000000000..df2df8a8f0 --- /dev/null +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/report/SW360ReportService.java @@ -0,0 +1,60 @@ +/* +SPDX-FileCopyrightText: © 2023 Siemens AG +SPDX-License-Identifier: EPL-2.0 +*/ +package org.eclipse.sw360.rest.resourceserver.report; + +import java.nio.ByteBuffer; +import java.util.List; + +import org.apache.thrift.TException; +import org.eclipse.sw360.datahandler.thrift.ThriftClients; +import org.eclipse.sw360.datahandler.thrift.components.ComponentService; +import org.eclipse.sw360.datahandler.thrift.projects.ProjectService; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class SW360ReportService { + + ThriftClients thriftClients = new ThriftClients(); + ProjectService.Iface projectclient = thriftClients.makeProjectClient(); + ComponentService.Iface componentclient = thriftClients.makeComponentClient(); + + public ByteBuffer getProjectBuffer(User user, boolean extendedByReleases) + throws TException { + return projectclient.getReportDataStream(user, extendedByReleases); + } + + public String getUploadedProjectPath(User user, boolean extendedByReleases) throws TException{ + return projectclient.getReportInEmail(user, extendedByReleases); + } + + public ByteBuffer getReportStreamFromURl(User user,boolean extendedByReleases, String token) + throws TException{ + return projectclient.downloadExcel(user,extendedByReleases, token); + } + public void sendExportSpreadsheetSuccessMail(String emailURL, String email) throws TException{ + projectclient.sendExportSpreadsheetSuccessMail(emailURL, email); + } + + public String getUploadedComponentPath(User sw360User, boolean withLinkedReleases) throws TException{ + return componentclient.getComponentReportInEmail(sw360User, withLinkedReleases); + } + + public ByteBuffer getComponentBuffer(User sw360User, boolean withLinkedReleases) throws TException{ + return componentclient.getComponentReportDataStream(sw360User, withLinkedReleases); + } + + public ByteBuffer getComponentReportStreamFromURl(User user,boolean extendedByReleases, String token) + throws TException{ + return componentclient.downloadExcel(user,extendedByReleases, token); + } + public void sendComponentExportSpreadsheetSuccessMail(String emailURL, String email) throws TException{ + componentclient.sendExportSpreadsheetSuccessMail(emailURL, email); + } +} \ No newline at end of file diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ApiSpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ApiSpecTest.java index d0456ae0a9..d699893c3c 100644 --- a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ApiSpecTest.java +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ApiSpecTest.java @@ -166,6 +166,7 @@ public void should_document_index() throws Exception { .andDo(this.documentationHandler.document( links( linkWithRel("sw360:users").description("The <>"), + linkWithRel("sw360:reports").description("The <>"), linkWithRel("sw360:projects").description("The <>"), linkWithRel("sw360:components").description("The <>"), linkWithRel("sw360:releases").description("The <>"), diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java index 11d57402c9..a543f25d0c 100644 --- a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ComponentSpecTest.java @@ -33,6 +33,7 @@ import org.eclipse.sw360.rest.resourceserver.TestHelper; import org.eclipse.sw360.rest.resourceserver.attachment.Sw360AttachmentService; import org.eclipse.sw360.rest.resourceserver.component.Sw360ComponentService; +import org.eclipse.sw360.rest.resourceserver.report.SW360ReportService; import org.eclipse.sw360.rest.resourceserver.user.Sw360UserService; import org.eclipse.sw360.rest.resourceserver.vulnerability.Sw360VulnerabilityService; import org.eclipse.sw360.rest.resourceserver.vendor.Sw360VendorService; @@ -53,12 +54,14 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.io.IOException; +import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; import static org.mockito.BDDMockito.given; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; @@ -94,6 +97,9 @@ public class ComponentSpecTest extends TestRestDocsSpecBase { @MockBean private Sw360VendorService vendorServiceMock; + + @MockBean + private SW360ReportService sw360ReportServiceMock; private Component angularComponent; @@ -261,6 +267,7 @@ public void before() throws TException, IOException { .setCreatedOn(new SimpleDateFormat("yyyy-MM-dd").format(new Date()))); given(this.componentServiceMock.getComponentsForUser(any())).willReturn(componentList); + given(this.sw360ReportServiceMock.getComponentBuffer(any(),anyBoolean())).willReturn(ByteBuffer.allocate(10000)); given(this.componentServiceMock.getRecentComponents(any())).willReturn(componentList); given(this.componentServiceMock.getComponentSubscriptions(any())).willReturn(componentList); given(this.componentServiceMock.getMyComponentsForUser(any())).willReturn(componentList); @@ -1161,4 +1168,48 @@ public void should_document_prepare_import_sbom_for_component() throws Exception .queryParam("type", "SPDX"); this.mockMvc.perform(builder).andExpect(status().isOk()).andDo(this.documentationHandler.document()); } + + @Test + public void should_document_get_component_report() throws Exception{ + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + mockMvc.perform(get("/api/reports") + .header("Authorization", "Bearer " + accessToken) + .param("withlinkedreleases", "true") + .param("mimetype", "xlsx") + .param("mailrequest", "false") + .param("module", "components") + .accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()) + .andDo(this.documentationHandler.document( + requestParameters( + parameterWithName("withlinkedreleases").description("Projects with linked releases. Possible values are ``"), + parameterWithName("mimetype").description("Projects download format. Possible values are ``"), + parameterWithName("mailrequest").description("Downloading project report requirted mail link. Possible values are ``"), + parameterWithName("module").description("module represent the project or component. Possible values are ``") + ))); + } + + @Test + public void should_document_get_component_report_with_mail_req() throws Exception{ + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + mockMvc.perform(get("/api/reports") + .header("Authorization", "Bearer " + accessToken) + .param("withlinkedreleases", "true") + .param("mimetype", "xlsx") + .param("mailrequest", "true") + .param("module", "components") + .accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()) + .andDo(this.documentationHandler.document( + requestParameters( + parameterWithName("withlinkedreleases").description("components with linked releases. Possible values are ``"), + parameterWithName("mimetype").description("components download format. Possible values are ``"), + parameterWithName("module").description("module represent the project or component. Possible values are ``"), + parameterWithName("mailrequest").description("Downloading components report requirted mail link. Possible values are ``") + ),responseFields( + subsectionWithPath("response").description("The response message displayed").optional(), + subsectionWithPath("url").description("The components download path will be displayed").optional() + ) + )); + } } diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java index 5bc4ef90b3..0f34d827bf 100644 --- a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ProjectSpecTest.java @@ -55,6 +55,7 @@ import org.eclipse.sw360.rest.resourceserver.licenseinfo.Sw360LicenseInfoService; import org.eclipse.sw360.rest.resourceserver.project.Sw360ProjectService; import org.eclipse.sw360.rest.resourceserver.release.Sw360ReleaseService; +import org.eclipse.sw360.rest.resourceserver.report.SW360ReportService; import org.eclipse.sw360.rest.resourceserver.user.Sw360UserService; import org.eclipse.sw360.rest.resourceserver.vulnerability.Sw360VulnerabilityService; import org.hamcrest.Matchers; @@ -74,6 +75,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.io.IOException; +import java.nio.ByteBuffer; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -89,6 +91,7 @@ import static org.eclipse.sw360.datahandler.thrift.MainlineState.OPEN; import static org.eclipse.sw360.datahandler.thrift.ReleaseRelationship.CONTAINED; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.when; @@ -134,6 +137,9 @@ public class ProjectSpecTest extends TestRestDocsSpecBase { @MockBean private Sw360VulnerabilityService vulnerabilityMockService; + @MockBean + private SW360ReportService sw360ReportServiceMock; + private Project project; private Project sBOMProject; private Set projectList = new HashSet<>(); @@ -319,6 +325,7 @@ public void before() throws TException, IOException { requestSummary.setRequestStatus(RequestStatus.SUCCESS); given(this.projectServiceMock.importSBOM(any(),any())).willReturn(requestSummary); + given(this.sw360ReportServiceMock.getProjectBuffer(any(),anyBoolean())).willReturn(ByteBuffer.allocate(10000)); given(this.projectServiceMock.getProjectsForUser(any(), any())).willReturn(projectList); given(this.projectServiceMock.getProjectForUserById(eq(project.getId()), any())).willReturn(project); given(this.projectServiceMock.getProjectForUserById(eq(project2.getId()), any())).willReturn(project2); @@ -1693,6 +1700,7 @@ public void should_document_get_project_count() throws Exception { fieldWithPath("count").description("Count of projects for a user.").optional() ))); } + @Test public void should_document_create_summary_administration() throws Exception { String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); @@ -1741,7 +1749,51 @@ public void should_document_create_summary_administration() throws Exception { subsectionWithPath("_embedded.sw360:moderators").description("An array of moderators"), subsectionWithPath("_embedded.sw360:vendors").description("An array of all component vendors with full name and link to their <>"), subsectionWithPath("_embedded.sw360:attachments").description("An array of all project attachments and link to their <>"), - subsectionWithPath("_links").description("<> to other resources") + subsectionWithPath("_links").description("<> to other resources")) + )); + } + + @Test + public void should_document_get_project_report() throws Exception{ + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + mockMvc.perform(get("/api/reports") + .header("Authorization", "Bearer " + accessToken) + .param("withlinkedreleases", "true") + .param("mimetype", "xlsx") + .param("mailrequest", "true") + .param("module", "projects") + .accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()) + .andDo(this.documentationHandler.document( + requestParameters( + parameterWithName("withlinkedreleases").description("Projects with linked releases. Possible values are ``"), + parameterWithName("mimetype").description("Projects download format. Possible values are ``"), + parameterWithName("mailrequest").description("Downloading project report requirted mail link. Possible values are ``"), + parameterWithName("module").description("module represent the project or component. Possible values are ``") + ),responseFields( + subsectionWithPath("response").description("The response message displayed").optional(), + subsectionWithPath("url").description("The project download path will be displayed").optional() + ) + )); + } + + @Test + public void should_document_get_project_report_without_mail_req() throws Exception{ + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + mockMvc.perform(get("/api/reports") + .header("Authorization", "Bearer " + accessToken) + .param("withlinkedreleases", "true") + .param("mimetype", "xlsx") + .param("mailrequest", "false") + .param("module", "projects") + .accept("application/xhtml+xml")) + .andExpect(status().isOk()) + .andDo(this.documentationHandler.document( + requestParameters( + parameterWithName("withlinkedreleases").description("Projects with linked releases. Possible values are ``"), + parameterWithName("mimetype").description("Projects download format. Possible values are ``"), + parameterWithName("mailrequest").description("Downloading project report requirted mail link. Possible values are ``"), + parameterWithName("module").description("module represent the project or component. Possible values are ``") ))); } }