-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(Rest): Create new endpoint to activate the department manually.
Signed-off-by: Nikesh kumar <[email protected]>
- Loading branch information
Showing
7 changed files
with
343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// | ||
// 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 | ||
// SPDX-FileCopyrightText: 2024, Siemens AG. Part of the SW360 Portal Project. | ||
// SPDX-FileContributor: Nikesh kumar <[email protected]> | ||
// | ||
|
||
[[resources-department]] | ||
=== Department | ||
|
||
The department resource is used to upload a department and its members. | ||
|
||
[[manually-active]] | ||
==== Manually Activating Department Import | ||
|
||
A `GET` request is used to import department data. | ||
|
||
===== Example Request | ||
include::{snippets}/should_document_import_department_manually/curl-request.adoc[] | ||
|
||
===== Example Response | ||
include::{snippets}/should_document_import_department_manually/http-response.adoc[] | ||
|
||
[[schedule-department]] | ||
==== Import Schedule Department. | ||
|
||
A `POST` request is used to import schedule department. | ||
|
||
===== Example Request | ||
include::{snippets}/should_document_import_schedule_department/curl-request.adoc[] | ||
|
||
===== Example Response | ||
include::{snippets}/should_document_import_schedule_department/http-response.adoc[] |
125 changes: 125 additions & 0 deletions
125
.../src/main/java/org/eclipse/sw360/rest/resourceserver/department/DepartmentController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* 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.department; | ||
|
||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; | ||
|
||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.apache.thrift.TException; | ||
import org.eclipse.sw360.datahandler.common.SW360Constants; | ||
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.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.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestMethod; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
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.security.SecurityRequirement; | ||
import lombok.NonNull; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@BasePathAwareController | ||
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) | ||
@RestController | ||
@SecurityRequirement(name = "tokenAuth") | ||
public class DepartmentController implements RepresentationModelProcessor<RepositoryLinksResource>{ | ||
public static final String DEPARTMENT_URL = "/department"; | ||
private static final Logger log = LogManager.getLogger(DepartmentController.class); | ||
|
||
@NonNull | ||
private final Sw360DepartmentService departmentService; | ||
|
||
@NonNull | ||
private final RestControllerHelper restControllerHelper; | ||
|
||
@Override | ||
public RepositoryLinksResource process(RepositoryLinksResource resource) { | ||
resource.add(linkTo(DepartmentController.class).slash("api" + DEPARTMENT_URL).withRel("department")); | ||
return resource; | ||
} | ||
|
||
@Operation( | ||
description = "Manually active the service.", | ||
tags = {"Department"} | ||
) | ||
@RequestMapping(value = DEPARTMENT_URL + "/manuallyactive", method = RequestMethod.POST) | ||
public ResponseEntity<RequestSummary> importDepartmentManually( | ||
@Parameter(description = "Request body containing the action key for manual import") | ||
@RequestBody Map<String, String> requestBody) | ||
throws TException { | ||
User sw360User = restControllerHelper.getSw360UserFromAuthentication(); | ||
|
||
String action = requestBody.get("action"); | ||
if (action == null || !SW360Constants.IMPORT_DEPARTMENT_MANUALLY.equals(action)) { | ||
log.warn("Unsupported or missing action: " + action); | ||
return ResponseEntity.badRequest().build(); | ||
} | ||
return processAction(sw360User); | ||
} | ||
|
||
private ResponseEntity<RequestSummary> processAction(User sw360User) { | ||
try { | ||
RequestSummary requestSummary = departmentService.importDepartmentManually(sw360User); | ||
return ResponseEntity.ok(requestSummary); | ||
} catch (TException e) { | ||
log.error("Error importing department", e); | ||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); | ||
} | ||
} | ||
|
||
@RequestMapping(value = DEPARTMENT_URL + "/scheduleImport", method = RequestMethod.POST) | ||
public ResponseEntity<Map<String, String>> scheduleImportDepartment( | ||
@Parameter(description = "The email of the user") | ||
@RequestParam String userEmail) { | ||
try { | ||
User user = restControllerHelper.getUserByEmail(userEmail); | ||
|
||
if (departmentService.isDepartmentScheduled(user)) { | ||
return ResponseEntity.status(HttpStatus.CONFLICT) | ||
.body(Collections.singletonMap("message", "Department import is already scheduled.")); | ||
} | ||
|
||
RequestSummary requestSummary = departmentService.scheduleImportDepartment(user); | ||
|
||
Map<String, String> response = new HashMap<>(); | ||
response.put("status", requestSummary.getRequestStatus().name()); | ||
response.put("message", "Department import scheduled successfully"); | ||
|
||
return ResponseEntity.ok(response); | ||
} catch (SW360Exception e) { | ||
log.error("Schedule check failed: {}", e.getMessage()); | ||
return ResponseEntity.status(HttpStatus.BAD_REQUEST) | ||
.body(Collections.singletonMap("error", e.getMessage())); | ||
} catch (TException e) { | ||
log.error("Schedule import department: {}", e.getMessage()); | ||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) | ||
.body(Collections.singletonMap("error", "Failed to schedule department import")); | ||
} | ||
} | ||
} |
83 changes: 83 additions & 0 deletions
83
...rc/main/java/org/eclipse/sw360/rest/resourceserver/department/Sw360DepartmentService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
* 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.department; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.apache.thrift.TException; | ||
import org.eclipse.sw360.datahandler.permissions.PermissionUtils; | ||
import org.eclipse.sw360.datahandler.thrift.RequestStatus; | ||
import org.eclipse.sw360.datahandler.thrift.RequestStatusWithBoolean; | ||
import org.eclipse.sw360.datahandler.thrift.RequestSummary; | ||
import org.eclipse.sw360.datahandler.thrift.SW360Exception; | ||
import org.eclipse.sw360.datahandler.thrift.ThriftClients; | ||
import org.eclipse.sw360.datahandler.thrift.schedule.ScheduleService; | ||
import org.eclipse.sw360.datahandler.thrift.users.User; | ||
import org.eclipse.sw360.datahandler.thrift.users.UserGroup; | ||
import org.eclipse.sw360.datahandler.thrift.users.UserService; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.security.access.AccessDeniedException; | ||
import org.springframework.stereotype.Service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
|
||
@Service | ||
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) | ||
public class Sw360DepartmentService { | ||
private static final Logger log = LogManager.getLogger(Sw360DepartmentService.class); | ||
|
||
@Value("${sw360.thrift-server-url:http://localhost:8080}") | ||
private String thriftServerUrl; | ||
|
||
public RequestSummary importDepartmentManually(User sw360User) throws TException { | ||
try { | ||
if (PermissionUtils.isUserAtLeast(UserGroup.ADMIN, sw360User)) { | ||
ThriftClients thriftClients = new ThriftClients(); | ||
UserService.Iface userClient = thriftClients.makeUserClient(); | ||
RequestSummary request = userClient.importFileToDB(); | ||
return request; | ||
} else { | ||
throw new AccessDeniedException("User is not admin"); | ||
} | ||
} catch (TException e) { | ||
log.error("Error occurred while scheduling service: " + e); | ||
throw e; | ||
} | ||
} | ||
|
||
public boolean isDepartmentScheduled(User user) throws TException { | ||
if (!PermissionUtils.isUserAtLeast(UserGroup.ADMIN, user)) { | ||
throw new AccessDeniedException("User is not an admin"); | ||
} | ||
ScheduleService.Iface scheduleClient = new ThriftClients().makeScheduleClient(); | ||
RequestStatusWithBoolean requestStatus = scheduleClient | ||
.isServiceScheduled(ThriftClients.IMPORT_DEPARTMENT_SERVICE, user); | ||
if (RequestStatus.SUCCESS.equals(requestStatus.getRequestStatus())) { | ||
return requestStatus.isAnswerPositive(); | ||
} else { | ||
throw new SW360Exception("Backend query for schedule status of department failed."); | ||
} | ||
} | ||
|
||
public RequestSummary scheduleImportDepartment(User user) throws TException { | ||
if (!PermissionUtils.isUserAtLeast(UserGroup.ADMIN, user)) { | ||
throw new AccessDeniedException("User is not an admin"); | ||
} | ||
ScheduleService.Iface scheduleClient = new ThriftClients().makeScheduleClient(); | ||
RequestStatusWithBoolean requestStatus = scheduleClient.isServiceScheduled(ThriftClients.IMPORT_DEPARTMENT_SERVICE, user); | ||
if (RequestStatus.SUCCESS.equals(requestStatus.getRequestStatus()) && requestStatus.isAnswerPositive()) { | ||
throw new SW360Exception("Department import is already scheduled."); | ||
} | ||
return scheduleClient.scheduleService(ThriftClients.IMPORT_DEPARTMENT_SERVICE); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
...rver/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/DepartmentSpecTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* 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.mockito.Mockito.when; | ||
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.apache.thrift.TException; | ||
import org.eclipse.sw360.datahandler.common.SW360Constants; | ||
import org.eclipse.sw360.datahandler.thrift.RequestStatus; | ||
import org.eclipse.sw360.datahandler.thrift.RequestSummary; | ||
import org.eclipse.sw360.datahandler.thrift.users.User; | ||
import org.eclipse.sw360.rest.resourceserver.TestHelper; | ||
import org.eclipse.sw360.rest.resourceserver.department.Sw360DepartmentService; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.boot.test.mock.mockito.MockBean; | ||
import org.springframework.hateoas.MediaTypes; | ||
import org.springframework.http.MediaType; | ||
|
||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
||
@RunWith(SpringJUnit4ClassRunner.class) | ||
public class DepartmentSpecTest extends TestRestDocsSpecBase { | ||
@Value("${sw360.test-user-id}") | ||
private String testUserId; | ||
|
||
@Value("${sw360.test-user-password}") | ||
private String testUserPassword; | ||
|
||
@MockBean | ||
private Sw360DepartmentService departmentServiceMock; | ||
private RequestSummary requestSummary = new RequestSummary(); | ||
|
||
@Before | ||
public void before() throws TException { | ||
User sw360User = new User(); | ||
sw360User.setId("123456789"); | ||
sw360User.setEmail("[email protected]"); | ||
sw360User.setFullname("John Doe"); | ||
given(this.userServiceMock.getUserByEmailOrExternalId("[email protected]")).willReturn(sw360User); | ||
given(this.departmentServiceMock.importDepartmentManually(any())).willReturn(requestSummary); | ||
given(this.departmentServiceMock.scheduleImportDepartment(any())).willReturn(requestSummary); | ||
when(departmentServiceMock.isDepartmentScheduled(sw360User)).thenReturn(false); | ||
} | ||
|
||
@Test | ||
public void should_document_import_department_manually() throws Exception { | ||
Map<String, Object> requestBody = new HashMap<>(); | ||
requestBody.put("action", SW360Constants.IMPORT_DEPARTMENT_MANUALLY); | ||
|
||
mockMvc.perform(post("/api/department/manuallyactive") | ||
.header("Authorization", TestHelper.generateAuthHeader(testUserId, testUserPassword)) | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.content(new ObjectMapper().writeValueAsString(requestBody)) | ||
.accept(MediaTypes.HAL_JSON)) | ||
.andExpect(status().isOk()); | ||
} | ||
|
||
@Test | ||
public void should_document_import_schedule_department() throws Exception { | ||
String userEmail = "[email protected]"; | ||
RequestSummary mockRequestSummary = new RequestSummary(); | ||
mockRequestSummary.setRequestStatus(RequestStatus.SUCCESS); | ||
when(departmentServiceMock.scheduleImportDepartment(any())).thenReturn(mockRequestSummary); | ||
mockMvc.perform(post("/api/department/scheduleImport") | ||
.header("Authorization", TestHelper.generateAuthHeader(testUserId, testUserPassword)) | ||
.param("userEmail", userEmail) | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.accept(MediaType.APPLICATION_JSON)) | ||
.andExpect(status().isOk()); | ||
} | ||
|
||
} |