From 043523c6c6ffd7dcfecc878f36ce329fa85c13b3 Mon Sep 17 00:00:00 2001 From: Nikesh kumar Date: Fri, 19 Jan 2024 13:20:05 +0530 Subject: [PATCH] feat(rest): Create new endpoint to download component template in csv format. Signed-off-by: Nikesh kumar --- .../src/docs/asciidoc/api-guide.adoc | 1 + .../src/docs/asciidoc/importExport.adoc | 25 +++++++ .../importexport/ImportExportController.java | 75 +++++++++++++++++++ .../Sw360ImportExportService.java | 55 ++++++++++++++ .../resourceserver/restdocs/ApiSpecTest.java | 1 + .../restdocs/ImportExportSpec.java | 71 ++++++++++++++++++ 6 files changed, 228 insertions(+) create mode 100644 rest/resource-server/src/docs/asciidoc/importExport.adoc create mode 100644 rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/ImportExportController.java create mode 100644 rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/Sw360ImportExportService.java create mode 100644 rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ImportExportSpec.java diff --git a/rest/resource-server/src/docs/asciidoc/api-guide.adoc b/rest/resource-server/src/docs/asciidoc/api-guide.adoc index 31feb10efe..25313e3959 100644 --- a/rest/resource-server/src/docs/asciidoc/api-guide.adoc +++ b/rest/resource-server/src/docs/asciidoc/api-guide.adoc @@ -307,3 +307,4 @@ include::obligations.adoc[] include::moderationRequests.adoc[] include::fossology.adoc[] include::schedule.adoc[] +include::importExport.adoc[] diff --git a/rest/resource-server/src/docs/asciidoc/importExport.adoc b/rest/resource-server/src/docs/asciidoc/importExport.adoc new file mode 100644 index 0000000000..aa661eb1fd --- /dev/null +++ b/rest/resource-server/src/docs/asciidoc/importExport.adoc @@ -0,0 +1,25 @@ +// +// Copyright Siemens AG, 2024. Part of the SW360 Portal Project. +// +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ +// +// SPDX-License-Identifier: EPL-2.0 +// + +[[resources-importExport]] +=== ImportExport + +The ImportExport resource is used to get and upload request. + +[[download-import-export]] +==== Download component template. + +A `GET` request help to download the component template in csv format. + +===== Example request +include::{snippets}/should_document_get_download_component_template/curl-request.adoc[] + +===== Example response +include::{snippets}/should_document_get_download_component_template/http-response.adoc[] \ No newline at end of file diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/ImportExportController.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/ImportExportController.java new file mode 100644 index 0000000000..3438cb1186 --- /dev/null +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/ImportExportController.java @@ -0,0 +1,75 @@ +/* + * Copyright Siemens AG, 2024-2025. + * Part of the SW360 Portal Project. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.eclipse.sw360.rest.resourceserver.importexport; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.thrift.TException; +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.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@BasePathAwareController +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +@RestController +@SecurityRequirement(name = "tokenAuth") +public class ImportExportController implements RepresentationModelProcessor { + + public static final String IMPORTEXPORT_URL = "/importExport"; + + @NonNull + private final RestControllerHelper restControllerHelper; + + @NonNull + private final Sw360ImportExportService importExportService; + + @Override + public RepositoryLinksResource process(RepositoryLinksResource resource) { + resource.add(linkTo(ImportExportController.class).slash("api/importExport").withRel("importExport")); + return resource; + } + + @Operation( + summary = "Download csv component template.", + description = "Download csv component template.", + tags = {"ImportExport"}, + parameters = { + @Parameter(name = "Accept", in = ParameterIn.HEADER, required = true, example = "application/zip"), + } + ) + @PreAuthorize("hasAuthority('WRITE')") + @RequestMapping(value = IMPORTEXPORT_URL + "/downloadComponentTemplate", method = RequestMethod.GET) + public void downloadLicenseArchive( HttpServletRequest request, HttpServletResponse response ) throws TException, IOException { + User sw360User = restControllerHelper.getSw360UserFromAuthentication(); + importExportService.getDownloadCsvComponentTemplate(sw360User,request,response); + } + +} diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/Sw360ImportExportService.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/Sw360ImportExportService.java new file mode 100644 index 0000000000..b37c0ccf01 --- /dev/null +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/importexport/Sw360ImportExportService.java @@ -0,0 +1,55 @@ +/* + * Copyright Siemens AG, 2024-2025. + * Part of the SW360 Portal Project. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.eclipse.sw360.rest.resourceserver.importexport; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.thrift.TException; +import org.eclipse.sw360.datahandler.common.SW360Utils; +import org.eclipse.sw360.datahandler.permissions.PermissionUtils; +import org.eclipse.sw360.datahandler.thrift.SW360Exception; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.datahandler.thrift.users.UserGroup; +import org.eclipse.sw360.exporter.CSVExport; +import org.eclipse.sw360.importer.ComponentCSVRecord; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.util.FileCopyUtils; + +import com.google.common.collect.ImmutableList; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class Sw360ImportExportService { + public void getDownloadCsvComponentTemplate(User sw360User, HttpServletRequest request, + HttpServletResponse response) throws TException, IOException { + String fileConstant="ComponentsReleasesVendorsSample.csv"; + if (!PermissionUtils.isUserAtLeast(UserGroup.ADMIN, sw360User)) { + throw new RuntimeException("Unable to download CSV component template. User is not admin"); + } + final Iterable> inputIterable = ImmutableList.of(ComponentCSVRecord.getSampleInputIterable()); + final Iterable csvHeaderIterable = ComponentCSVRecord.getCSVHeaderIterable(); + + ByteArrayInputStream byteArrayInputStream = CSVExport.createCSV(csvHeaderIterable, inputIterable); + String filename = String.format(fileConstant, SW360Utils.getCreatedOn()); + response.setHeader("Content-Disposition", String.format("Components; filename=\"%s\"", filename)); + FileCopyUtils.copy(byteArrayInputStream, response.getOutputStream()); + + } +} 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 ab953728f2..4e5c6b19ab 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 @@ -184,6 +184,7 @@ public void should_document_index() throws Exception { linkWithRel("sw360:moderationRequests").description("The <>"), linkWithRel("sw360:fossology").description("The <>"), linkWithRel("sw360:schedule").description("The <>"), + linkWithRel("sw360:importExport").description("The <>"), linkWithRel("curies").description("The Curies for documentation"), linkWithRel("profile").description("The profiles of the REST resources") ), diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ImportExportSpec.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ImportExportSpec.java new file mode 100644 index 0000000000..3245420789 --- /dev/null +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ImportExportSpec.java @@ -0,0 +1,71 @@ +/* + * Copyright Siemens AG, 2024-2025. + * Part of the SW360 Portal Project. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.eclipse.sw360.rest.resourceserver.restdocs; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.IOException; + +import org.apache.thrift.TException; +import org.eclipse.sw360.rest.resourceserver.TestHelper; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.rest.resourceserver.importexport.Sw360ImportExportService; +import org.eclipse.sw360.rest.resourceserver.user.Sw360UserService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.hateoas.MediaTypes; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +public class ImportExportSpec extends TestRestDocsSpecBase { + + @Value("${sw360.test-user-id}") + private String testUserId; + + @Value("${sw360.test-user-password}") + private String testUserPassword; + + @MockBean + private Sw360UserService userServiceMock; + + @MockBean + private Sw360ImportExportService importExportService; + + @Before + @SuppressWarnings("unchecked") + public void before() throws TException, IOException { + User sw360User = new User(); + sw360User.setId("123456789"); + sw360User.setEmail("admin@sw360.org"); + sw360User.setFullname("John Doe"); + given(this.userServiceMock.getUserByEmailOrExternalId("admin@sw360.org")).willReturn(sw360User); + Mockito.doNothing().when(importExportService).getDownloadCsvComponentTemplate(any(), any(), any()); + + } + + @Test + public void should_document_get_download_component_template() throws Exception { + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + mockMvc.perform(get("/api/importExport/downloadComponentTemplate") + .header("Authorization", "Bearer " + accessToken) + .accept(MediaTypes.HAL_JSON)) + .andExpect(status().isOk()); + } + +}