Skip to content

Commit

Permalink
feat(rest): create new endpoint to delete ModerationRequests by id.
Browse files Browse the repository at this point in the history
Signed-off-by: Nikesh kumar <[email protected]>
  • Loading branch information
Nikesh kumar committed Apr 1, 2024
1 parent f051d63 commit 4d0c45e
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 17 deletions.
12 changes: 12 additions & 0 deletions rest/resource-server/src/docs/asciidoc/moderationRequests.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,15 @@ include::{snippets}/should_document_get_moderationrequests_submission/curl-reque

===== Example response
include::{snippets}/should_document_get_moderationrequests_submission/http-response.adoc[]

[[resources-moderationRequest-delete]]
==== Delete Moderation Requests

A `DELETE` method will delete list of moderation request.

===== Example request
include::{snippets}/should_document_get_moderationrequests_delete/curl-request.adoc[]

===== Example response
include::{snippets}/should_document_get_moderationrequests_delete/http-response.adoc[]

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.sw360.datahandler.resourcelists.ResourceClassNotFoundException;
import org.eclipse.sw360.datahandler.thrift.ModerationState;
import org.eclipse.sw360.datahandler.thrift.PaginationData;
import org.eclipse.sw360.datahandler.thrift.RequestStatus;
import org.eclipse.sw360.datahandler.thrift.components.Component;
import org.eclipse.sw360.datahandler.thrift.components.Release;
import org.eclipse.sw360.datahandler.thrift.moderation.DocumentType;
Expand All @@ -45,13 +46,15 @@
import org.springframework.data.domain.Pageable;
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.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.MediaTypes;
import org.springframework.hateoas.server.RepresentationModelProcessor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;

Expand Down Expand Up @@ -342,4 +345,45 @@ private ResponseEntity<CollectionModel<ModerationRequest>> getModerationResponse
HttpStatus status = resources == null ? HttpStatus.NO_CONTENT : HttpStatus.OK;
return new ResponseEntity<>(resources, status);
}

@Operation(
summary = "Delete moderation request.",
description = "Delete delete moderation request of the service.",
tags = {"ModerationRequest"}
)
@PreAuthorize("hasAuthority('WRITE')")
@RequestMapping(value = MODERATION_REQUEST_URL + "/delete", method = RequestMethod.DELETE)
public ResponseEntity<?> deleteModerationRequest(HttpServletRequest request, @RequestBody List<String> ids,
ModerationRequest moderationRequest) throws TException {
User sw360User = restControllerHelper.getSw360UserFromAuthentication();
HttpStatus status;
List<RequestStatus> requestStatusList = new ArrayList<>();
List<String> incorrectIds = new ArrayList<>();
List<String> correctIds = new ArrayList<>();

for (String id : ids) {
try {
moderationRequest = sw360ModerationRequestService.getModerationRequestById(id);
RequestStatus requestStatus = sw360ModerationRequestService.deleteModerationRequestInfo(sw360User, id,
moderationRequest);
requestStatusList.add(requestStatus);
correctIds.add(id);
} catch (ResourceNotFoundException ex) {
incorrectIds.add(id);
}
}

if (requestStatusList == null || requestStatusList.isEmpty()) {
return ResponseEntity.badRequest().body("No moderation request IDs provided.");
}

Map<String, Object> response = new HashMap<>();
if (!incorrectIds.isEmpty()) {
response.put("Incorrect moderation request Ids", incorrectIds);
}
if (!correctIds.isEmpty()) {
response.put("Delete moderation request Ids", correctIds);
}
return ResponseEntity.status(HttpStatus.ACCEPTED).body(response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@
import lombok.RequiredArgsConstructor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.thrift.TApplicationException;
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.permissions.PermissionUtils;
import org.eclipse.sw360.datahandler.thrift.ModerationState;
import org.eclipse.sw360.datahandler.thrift.PaginationData;
import org.eclipse.sw360.datahandler.thrift.RemoveModeratorRequestStatus;
import org.eclipse.sw360.datahandler.thrift.RequestStatus;
import org.eclipse.sw360.datahandler.thrift.SW360Exception;
import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest;
import org.eclipse.sw360.datahandler.thrift.moderation.ModerationService;
import org.eclipse.sw360.datahandler.thrift.users.User;
import org.eclipse.sw360.datahandler.thrift.users.UserGroup;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -49,7 +53,7 @@ public class Sw360ModerationRequestService {
private String thriftServerUrl;

public static boolean isOpenModerationRequest(@NotNull ModerationRequest moderationRequest) {
return moderationRequest.getModerationState() == ModerationState.PENDING || moderationRequest.getModerationState() == ModerationState.INPROGRESS;
return moderationRequest.getModerationState() == ModerationState.PENDING || moderationRequest.getModerationState() == ModerationState.INPROGRESS || moderationRequest.getModerationState() == ModerationState.APPROVED;
}

private ModerationService.Iface getThriftModerationClient() throws TTransportException {
Expand All @@ -65,21 +69,28 @@ private ModerationService.Iface getThriftModerationClient() throws TTransportExc
* @return Moderation Request
* @throws TException Appropriate exception if request does not exists or not accessible.
*/
public ModerationRequest getModerationRequestById(String requestId) throws TException {
try {
return getThriftModerationClient().getModerationRequestById(requestId);
} catch (SW360Exception sw360Exp) {
if (sw360Exp.getErrorCode() == 404) {
throw new ResourceNotFoundException("Requested ModerationRequest not found");
} else if (sw360Exp.getErrorCode() == 403) {
throw new AccessDeniedException(
"ModerationRequest or its Linked Project are restricted and / or not accessible");
} else {
log.error("Error fetching moderation request by id: " + sw360Exp.getMessage());
throw sw360Exp;
}
}
}
public ModerationRequest getModerationRequestById(String requestId) throws TException, TApplicationException {
ModerationRequest moderationRequest = null;
Map<String, String> responseMap = new HashMap<>();
try {
moderationRequest = getThriftModerationClient().getModerationRequestById(requestId);
} catch (TApplicationException tAppExp) {
log.error("Error fetching moderation request by id: " + tAppExp.getMessage());
throw new ResourceNotFoundException("Requested ModerationRequest not found: " + requestId, tAppExp);
} catch (SW360Exception sw360Exp) {
if (sw360Exp.getErrorCode() == 404) {
throw new ResourceNotFoundException("Requested ModerationRequest not found: " + requestId);
} else if (sw360Exp.getErrorCode() == 403) {
throw new AccessDeniedException(
"ModerationRequest or its Linked Project are restricted and / or not accessible");
} else {
log.error("Error fetching moderation request by id: " + sw360Exp.getMessage());
throw sw360Exp;
}
}

return moderationRequest;
}

/**
* Get paginated list of moderation requests where user is one of the
Expand Down Expand Up @@ -253,4 +264,28 @@ public ModerationState assignRequest(@NotNull ModerationRequest request, @NotNul
getThriftModerationClient().setInProgress(request.getId(), reviewer);
return ModerationState.INPROGRESS;
}

public RequestStatus deleteModerationRequestInfo(@NotNull User sw360User, @NotNull String id, @NotNull ModerationRequest moderationRequest)
throws TTransportException, TException {
RequestStatus requestStatus = null;
if (PermissionUtils.isUserAtLeast(UserGroup.ADMIN, sw360User)) {
if (moderationRequest.getModerationState() == ModerationState.PENDING ||
moderationRequest.getModerators().contains(sw360User.getEmail())) {
ModerationState moderationState = rejectRequest(moderationRequest, "Rejected by admin", sw360User);
if (moderationState == ModerationState.REJECTED || moderationState == ModerationState.APPROVED) {
requestStatus = getThriftModerationClient().deleteModerationRequest(id, sw360User);
}
}
} else if (!isOpenModerationRequest(moderationRequest)) {
throw new InvalidParameterException("Moderation request is not in open state.");
} else if (!moderationRequest.getModerators().contains(sw360User.getEmail())) {
throw new AccessDeniedException("User is not assigned as a moderator for the request.");
} else {
requestStatus = getThriftModerationClient().deleteModerationRequest(id, sw360User);
}
if (requestStatus == null) {
throw new IllegalStateException("Request status is null.");
}
return requestStatus;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.apache.thrift.TException;
import org.eclipse.sw360.datahandler.thrift.ModerationState;
import org.eclipse.sw360.datahandler.thrift.PaginationData;
import org.eclipse.sw360.datahandler.thrift.RequestStatus;
import org.eclipse.sw360.datahandler.thrift.Visibility;
import org.eclipse.sw360.datahandler.thrift.components.ComponentType;
import org.eclipse.sw360.datahandler.thrift.components.ECCStatus;
Expand Down Expand Up @@ -52,8 +53,10 @@

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.when;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
Expand All @@ -62,6 +65,7 @@
import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath;
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand All @@ -84,6 +88,9 @@ public class ModerationRequestSpecTest extends TestRestDocsSpecBase {
@MockBean
private Sw360ModerationRequestService moderationRequestServiceMock;

@MockBean
private ModerationRequest moderationRequest;

@Before
public void before() throws TException, IOException {
Set<String> moderatorList = new HashSet<>();
Expand Down Expand Up @@ -129,7 +136,7 @@ public void before() throws TException, IOException {
project2Deletions.setProjectType(ProjectType.CUSTOMER);
project2Deletions.setVisbility(Visibility.BUISNESSUNIT_AND_MODERATORS);

ModerationRequest moderationRequest = new ModerationRequest();
moderationRequest = new ModerationRequest();
moderationRequest.setId("MR-101");
moderationRequest.setTimestamp(System.currentTimeMillis() / 1000L - 172800);
moderationRequest.setDocumentId("R-101");
Expand Down Expand Up @@ -494,4 +501,18 @@ public void should_document_get_moderationrequests_submission() throws Exception
subsectionWithPath("_links").description("<<resources-index-links,Links>> to other resources")
)));
}

@Test
public void should_document_get_moderationrequests_delete() throws Exception {
String accessToken = TestHelper.getAccessToken(mockMvc, testUserId, testUserPassword);
when(moderationRequestServiceMock.getModerationRequestById(anyString())).thenReturn(new ModerationRequest());
when(moderationRequestServiceMock.deleteModerationRequestInfo(any(User.class), anyString(), any(ModerationRequest.class)))
.thenReturn(RequestStatus.SUCCESS);
mockMvc.perform(delete("/api/moderationrequest/delete/")
.content("[\"id1\", \"id2\"]")
.header("Authorization", "Bearer " + accessToken)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaTypes.HAL_JSON))
.andExpect(status().isOk());
}
}

0 comments on commit 4d0c45e

Please sign in to comment.