diff --git a/rest/resource-server/src/docs/asciidoc/api-guide.adoc b/rest/resource-server/src/docs/asciidoc/api-guide.adoc index 293e1f1009..648b4288e4 100644 --- a/rest/resource-server/src/docs/asciidoc/api-guide.adoc +++ b/rest/resource-server/src/docs/asciidoc/api-guide.adoc @@ -305,3 +305,5 @@ include::changeLogs.adoc[] include::clearingRequests.adoc[] include::obligations.adoc[] include::moderationRequests.adoc[] +include::fossology.adoc[] + diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/admin/fossology/FossologyAdminController.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/admin/fossology/FossologyAdminController.java new file mode 100644 index 0000000000..bae8776f24 --- /dev/null +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/admin/fossology/FossologyAdminController.java @@ -0,0 +1,72 @@ +package org.eclipse.sw360.rest.resourceserver.admin.fossology; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; + +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.THttpClient; +import org.apache.thrift.transport.TTransportException; +import org.eclipse.sw360.datahandler.thrift.ConfigContainer; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.RequestSummary; +import org.eclipse.sw360.datahandler.thrift.SW360Exception; +import org.eclipse.sw360.datahandler.thrift.fossology.FossologyService; +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.beans.factory.annotation.Value; +import org.springframework.data.rest.webmvc.BasePathAwareController; +import org.springframework.data.rest.webmvc.RepositoryLinksResource; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.hateoas.server.RepresentationModelProcessor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.HttpStatus.Series; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import io.swagger.v3.oas.annotations.Parameter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@BasePathAwareController +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class FossologyAdminController implements RepresentationModelProcessor { + public static final String FOSSOLOGY_URL = "/fossology"; + + @NonNull + private final RestControllerHelper restControllerHelper; + + @NonNull + Sw360FossologyAdminServices sw360FossologyAdminServices; + + @Override + public RepositoryLinksResource process(RepositoryLinksResource resource) { + resource.add(linkTo(FossologyAdminController.class).slash("api" + FOSSOLOGY_URL).withRel("fossology")); + return resource; + } + + @RequestMapping(value = FOSSOLOGY_URL + "/SaveConfig", method = RequestMethod.POST) + public ResponseEntity saveConfigration( + @Parameter(description = "The url need to be uploaded.") @RequestParam(value = "url", required = true) String url, + @Parameter(description = "give the folder ID.") @RequestParam(value = "folderId", required = true) String folderId, + @Parameter(description = "put the token ID.") @RequestParam(value = "token", required = true) String token) + throws TException { + try { + User sw360User = restControllerHelper.getSw360UserFromAuthentication(); + sw360FossologyAdminServices.saveconfig(sw360User, url, folderId, token); + } catch (Exception e) { + throw new TException(e.getMessage()); + } + return ResponseEntity.ok(Series.SUCCESSFUL); + + } +} diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/admin/fossology/Sw360FossologyAdminServices.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/admin/fossology/Sw360FossologyAdminServices.java new file mode 100644 index 0000000000..5cb6afa810 --- /dev/null +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/admin/fossology/Sw360FossologyAdminServices.java @@ -0,0 +1,69 @@ +package org.eclipse.sw360.rest.resourceserver.admin.fossology; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.THttpClient; +import org.apache.thrift.transport.TTransportException; +import org.eclipse.sw360.datahandler.thrift.ConfigContainer; +import org.eclipse.sw360.datahandler.thrift.RequestStatus; +import org.eclipse.sw360.datahandler.thrift.SW360Exception; +import org.eclipse.sw360.datahandler.thrift.ThriftClients; +import org.eclipse.sw360.datahandler.thrift.fossology.FossologyService; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class Sw360FossologyAdminServices { + + @Value("${sw360.thrift-server-url:http://localhost:8080}") + private String thriftServerUrl; + + private static FossologyService.Iface fossologyClient; + public static Sw360FossologyAdminServices instance; + private boolean fossologyConnectionEnabled; + + String key; + + public void saveconfig(User sw360User, String url, String folderId, String token) throws TException { + FossologyService.Iface client = getThriftFossologyClient(); + ConfigContainer fossologyConfig = client.getFossologyConfig(); + + Map> configKeyToValues = new HashMap<>(); + setKeyValuePair(configKeyToValues, key, url, folderId, token); + fossologyConfig.setConfigKeyToValues(configKeyToValues); + } + + public FossologyService.Iface getThriftFossologyClient() throws TTransportException { + if (fossologyClient == null) { + if (thriftServerUrl == null || thriftServerUrl.isEmpty()) { + throw new TTransportException("Invalid thriftServerUrl"); + } + + THttpClient thriftClient = new THttpClient(thriftServerUrl + "/fossology/thrift"); + TProtocol protocol = new TCompactProtocol(thriftClient); + fossologyClient = new FossologyService.Client(protocol); + } + + return fossologyClient; + } + + private void setKeyValuePair(Map> map, String key, String url, String folderId, + String token) { + map.computeIfAbsent(key, k -> new HashSet<>()).addAll(Set.of(url, folderId, token)); + } + +} 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 46f2fe2c5a..9aeee2ed72 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 @@ -182,6 +182,7 @@ public void should_document_index() throws Exception { linkWithRel("sw360:clearingRequests").description("The <>"), linkWithRel("sw360:obligations").description("The <>"), linkWithRel("sw360:moderationRequests").description("The <>"), + linkWithRel("sw360:fossology").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/fossologySpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/fossologySpecTest.java new file mode 100644 index 0000000000..5afa703767 --- /dev/null +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/fossologySpecTest.java @@ -0,0 +1,94 @@ +/* + * Copyright Siemens AG, 2017-2018. + * Copyright Bosch Software Innovations GmbH, 2017. + * 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.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.IOException; + +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.transport.THttpClient; +import org.apache.thrift.transport.TTransportException; +import org.eclipse.sw360.datahandler.thrift.ConfigContainer; +import org.eclipse.sw360.datahandler.thrift.fossology.FossologyService; +import org.eclipse.sw360.datahandler.thrift.users.User; +import org.eclipse.sw360.rest.resourceserver.TestHelper; +import org.eclipse.sw360.rest.resourceserver.admin.fossology.Sw360FossologyAdminServices; +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 fossologySpecTest extends TestRestDocsSpecBase { + + @Value("${sw360.test-user-id}") + private String testUserId; + + @Value("${sw360.test-user-password}") + private String testUserPassword; + + @MockBean + Sw360FossologyAdminServices fossologyAdminServices; + + @MockBean + private Sw360UserService userServiceMock; + + @MockBean + FossologyService.Iface fossologyClient; + + @MockBean + private ConfigContainer fossologyConfig; + @MockBean + private THttpClient mockThriftClient; + @MockBean + private TCompactProtocol mockProtocol; + @MockBean + private FossologyService.Client mockFossologyClient; + private String thriftServerUrl = "http://localhost:8080"; + + @Before + public void before() throws TException, IOException,TTransportException { + fossologyClient = mock(FossologyService.Iface.class); + User sw360User = new User(); + sw360User.setId("123456789"); + sw360User.setEmail("admin@sw360.org"); + sw360User.setFullname("John Doe"); + given(this.userServiceMock.getUserByEmailOrExternalId("admin@sw360.org")).willReturn( + new User("admin@sw360.org", "sw360").setId("123456789")); + when(fossologyAdminServices.getThriftFossologyClient()).thenReturn(fossologyClient); + when(fossologyClient.getFossologyConfig()).thenReturn(fossologyConfig); + Mockito.doNothing().when(fossologyAdminServices).saveconfig(any(), any(), any(), any()); + } + + @Test + public void should_document_save_configuration() throws Exception { + String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword); + mockMvc.perform(post("/api/fossology/SaveConfig") + .contentType(MediaTypes.HAL_JSON) + .header("Authorization", "Bearer " + accessToken)) + .andExpect(status().isOk()); + } + +}