Skip to content

Commit

Permalink
feat(api): new endpoint /mySubmissions
Browse files Browse the repository at this point in the history
New endpoint `/moderationrequest/mySubmissions` to get moderation
requests submitted by the user.

Also, refactor the `ModerationRequestController` to use
`ModerationRequestController.getModerationResponseEntity()`

Signed-off-by: Gaurav Mishra <[email protected]>
  • Loading branch information
GMishx committed Feb 20, 2024
1 parent e6dc931 commit ed7e431
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,13 @@ public List<ModerationRequest> getRequestsByRequestingUser(User user) throws TEx
return handler.getRequestsByRequestingUser(user.getEmail());
}

@Override
public List<ModerationRequest> getRequestsByRequestingUserWithPagination(User user, PaginationData pageData) throws TException {
assertUser(user);

return handler.getRequestsByRequestingUserWithPagination(user.getEmail(), pageData);
}

@Override
public ClearingRequest getClearingRequestByProjectId(String projectId, User user) throws TException {
assertId(projectId);
Expand Down Expand Up @@ -372,6 +379,12 @@ public Map<String, Long> getCountByModerationState(User user) throws TException
return handler.getCountByModerationState(user.getEmail());
}

@Override
public Map<String, Long> getCountByRequester(User user) throws TException {
assertUser(user);
return handler.getCountByRequester(user.getEmail());
}

@Override
public Map<PaginationData, List<ModerationRequest>> getRequestsByModeratorWithPagination(User user,
PaginationData pageData, boolean open) throws TException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ public List<ModerationRequest> getRequestsByRequestingUser(String user) {
return repository.getRequestsByRequestingUser(user);
}

public List<ModerationRequest> getRequestsByRequestingUserWithPagination(String user, PaginationData pageData) {
return repository.getRequestsByRequestingUserWithPagination(user, pageData);
}

public ClearingRequest getClearingRequestByProjectId(String projectId, User user) throws SW360Exception {
projectDatabaseHandler.getProjectById(projectId, user); // check if user have READ access to project.
return clearingRequestRepository.getClearingRequestByProjectId(projectId);
Expand Down Expand Up @@ -890,6 +894,10 @@ public Map<String, Long> getCountByModerationState(String moderator) {
return repository.getCountByModerationState(moderator);
}

public Map<String, Long> getCountByRequester(String moderator) {
return repository.getCountByRequester(moderator);
}

public Set<String> getRequestingUserDepts() {
return repository.getRequestingUserDepts();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,19 @@ public class ModerationRequestRepository extends SummaryAwareRepository<Moderati
" }" +
"}";

private static final String COUNTBYREQUESTER = "function(doc) {" +
" if (doc.type == 'moderation') {" +
" emit([doc.requestingUser], null);" +
" }" +
"}";

public ModerationRequestRepository(DatabaseConnectorCloudant db) {
super(ModerationRequest.class, db, new ModerationRequestSummary());
Map<String, MapReduce> views = new HashMap<String, MapReduce>();
views.put("all", createMapReduce(ALL, null));
views.put("byRequestingUsersDeptView", createMapReduce(REQUESTING_USERS_VIEW, null));
views.put("countByModerationState", createMapReduce(COUNTBYMODERATIONSTATE, "_count"));
views.put("countByRequester", createMapReduce(COUNTBYREQUESTER, "_count"));
initStandardDesignDocument(views, db);
createIndex("byModerators", new String[] {"moderators"}, db);
createIndex("byDate", new String[] {"timestamp"}, db);
Expand Down Expand Up @@ -260,6 +267,29 @@ public List<ModerationRequest> getRequestsByRequestingUser(String user) {
return makeSummaryFromFullDocs(SummaryType.SHORT, mrs);
}

public List<ModerationRequest> getRequestsByRequestingUserWithPagination(String user, PaginationData pageData) {
final int rowsPerPage = pageData.getRowsPerPage();
final boolean ascending = pageData.isAscending();
final int skip = pageData.getDisplayStart();
final Selector typeSelector = eq("type", "moderation");
final Selector filterByModeratorSelector = eq("requestingUser", user);
final Selector finalSelector = and(typeSelector, filterByModeratorSelector);
QueryBuilder qb = new QueryBuilder(finalSelector);
qb.limit(rowsPerPage);
qb.skip(skip);
qb.useIndex("byUsers");
qb = ascending ? qb.sort(Sort.asc("timestamp")) : qb.sort(Sort.desc("timestamp"));

List<ModerationRequest> modReqs = Lists.newArrayList();
try {
QueryResult<ModerationRequest> queryResult = getConnector().getQueryResult(qb.build(), ModerationRequest.class);
modReqs = queryResult.getDocs();
} catch (Exception e) {
log.error("Error getting moderation requests", e);
}
return modReqs;
}

public Map<String, Long> getCountByModerationState(String moderator) {
Map<String, Long> countByModerationState = Maps.newHashMap();
List<ComplexKey> keys = prepareKeys(moderator, true);
Expand All @@ -282,6 +312,27 @@ public Map<String, Long> getCountByModerationState(String moderator) {
return countByModerationState;
}

public Map<String, Long> getCountByRequester(String user) {
Map<String, Long> countByModerationState = Maps.newHashMap();

List<ComplexKey> keys = prepareKeys(user, true);
ViewRequest<ComplexKey, Long> countReq = getConnector()
.createQuery(ModerationRequest.class, "countByRequester").newRequest(Key.Type.COMPLEX, Long.class)
.startKey(keys.get(0)).endKey(keys.get(1)).group(true).groupLevel(2).reduce(true).build();
try {
ViewResponse<ComplexKey, Long> response = countReq.getResponse();
if (null != response) {
countByModerationState = response.getRows().stream().collect(Collectors.toMap(key -> {
String json = key.getKey().toJson();
return json.replaceAll("[\\[\\]\"]", "");
}, ViewResponse.Row::getValue));
}
} catch (IOException e) {
log.error("Error getting count of moderation requests based on moderation state", e);
}
return countByModerationState;
}

public Set<String> getRequestingUserDepts() {
Set<String> requestingUserDepts = Sets.newHashSet();
ViewRequest<String, Object> query = getConnector()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,26 @@

package org.eclipse.sw360.datahandler.resourcelists;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.eclipse.sw360.datahandler.common.SW360Constants;
import org.eclipse.sw360.datahandler.thrift.changelogs.ChangeLogs;
import org.eclipse.sw360.datahandler.thrift.components.Component;
import org.eclipse.sw360.datahandler.thrift.components.Release;
import org.eclipse.sw360.datahandler.thrift.moderation.ModerationRequest;
import org.eclipse.sw360.datahandler.thrift.packages.Package;
import org.eclipse.sw360.datahandler.thrift.projects.Project;
import org.eclipse.sw360.datahandler.thrift.search.SearchResult;
import org.eclipse.sw360.datahandler.thrift.users.User;
import org.eclipse.sw360.datahandler.thrift.vendors.Vendor;
import org.eclipse.sw360.datahandler.thrift.search.SearchResult;
import org.eclipse.sw360.datahandler.thrift.vulnerabilities.VulnerabilityDTO;
import org.eclipse.sw360.datahandler.thrift.vulnerabilities.Vulnerability;
import org.eclipse.sw360.datahandler.thrift.vulnerabilities.VulnerabilityDTO;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class ResourceComparatorGenerator<T> {

Expand Down Expand Up @@ -133,6 +133,10 @@ private static Map<ModerationRequest._Fields, Comparator<ModerationRequest>> gen
Comparator.comparing(ModerationRequest::getRequestingUser, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)));
moderationRequestMap.put(ModerationRequest._Fields.DOCUMENT_TYPE,
Comparator.comparing(c -> Optional.ofNullable(c.getDocumentType()).map(Object::toString).orElse(null), Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)));
moderationRequestMap.put(ModerationRequest._Fields.DOCUMENT_NAME,
Comparator.comparing(ModerationRequest::getDocumentName, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)));
moderationRequestMap.put(ModerationRequest._Fields.MODERATION_STATE,
Comparator.comparing(c -> Optional.ofNullable(c.getModerationState()).map(Object::toString).orElse(null), Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)));
return Collections.unmodifiableMap(moderationRequestMap);
}

Expand Down Expand Up @@ -261,6 +265,15 @@ public Comparator<T> generateComparator(String type, List<String> properties) th
}
}
return generateVulComparatorWithFields(type, vul);
case SW360Constants.TYPE_MODERATION:
List<ModerationRequest._Fields> modFields = new ArrayList<>();
for (String property : properties) {
ModerationRequest._Fields field = ModerationRequest._Fields.findByName(property);
if (field != null) {
modFields.add(field);
}
}
return generateModerationRequestComparatorWithFields(type, modFields);
default:
throw new ResourceClassNotFoundException("No comparator for resource class with name " + type);
}
Expand Down Expand Up @@ -356,6 +369,16 @@ public Comparator<T> generateVulComparatorWithFields(String type, List<Vulnerabi
}
}

public Comparator<T> generateModerationRequestComparatorWithFields(
String type, List<ModerationRequest._Fields> fields) throws ResourceClassNotFoundException {
switch (type) {
case SW360Constants.TYPE_MODERATION:
return (Comparator<T>) moderationComparator(fields);
default:
throw new ResourceClassNotFoundException("No comparator for resource class with name " + type);
}
}


private Comparator<Component> componentComparator(List<Component._Fields> fields) {
Comparator<Component> comparator = Comparator.comparing(x -> true);
Expand Down Expand Up @@ -477,6 +500,18 @@ private Comparator<Vulnerability> vulnComparator(List<Vulnerability._Fields> fie
return comparator;
}

private Comparator<ModerationRequest> moderationComparator(List<ModerationRequest._Fields> fields) {
Comparator<ModerationRequest> comparator = Comparator.comparing(x -> true);
for (ModerationRequest._Fields field : fields) {
Comparator<ModerationRequest> fieldComparator = moderationRequestMap.get(field);
if (fieldComparator != null) {
comparator = comparator.thenComparing(fieldComparator);
}
}
comparator = comparator.thenComparing(defaultModerationRequestComparator());
return comparator;
}

private Comparator<Component> defaultComponentComparator() {
return componentMap.get(Component._Fields.NAME);
}
Expand Down
10 changes: 10 additions & 0 deletions libraries/datahandler/src/main/thrift/moderation.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,11 @@ service ModerationService {
**/
list<ModerationRequest> getRequestsByRequestingUser(1: User user);

/**
* get list of moderation requests where user is requesting user, paginated
**/
list<ModerationRequest> getRequestsByRequestingUserWithPagination(1: User user, 2: PaginationData pageData);

/**
* delete moderation request specified by id if user is requesting user of moderation request
**/
Expand Down Expand Up @@ -334,6 +339,11 @@ service ModerationService {
**/
map<string, i64> getCountByModerationState(1: User user);

/**
* get count of moderation requests by a requester
**/
map<string, i64> getCountByRequester(1: User user);

/**
* get requesting users departments
**/
Expand Down
17 changes: 17 additions & 0 deletions rest/resource-server/src/docs/asciidoc/moderationRequests.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,20 @@ include::{snippets}/should_document_get_moderationrequests_assign/curl-request.a

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

[[resources-moderationRequest-submission]]
==== Get Submitted Moderation Requests

A `GET` will pull <<resources-moderationRequest, ModerationRequest>> which are created by the requesting user.

===== Request parameter
include::{snippets}/should_document_get_moderationrequests_submission/request-parameters.adoc[]

===== Response structure
include::{snippets}/should_document_get_moderationrequests_submission/response-fields.adoc[]

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

===== Example response
include::{snippets}/should_document_get_moderationrequests_submission/http-response.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -101,22 +101,14 @@ public ResponseEntity<CollectionModel<ModerationRequest>> getModerationRequests(
) throws TException, ResourceClassNotFoundException, URISyntaxException {
User sw360User = restControllerHelper.getSw360UserFromAuthentication();
List<ModerationRequest> moderationRequests = sw360ModerationRequestService.getRequestsByModerator(sw360User, pageable);
int totalCount = (int) sw360ModerationRequestService.getTotalCountOfRequests(sw360User);
PaginationResult<ModerationRequest> paginationResult = restControllerHelper.paginationResultFromPaginatedList(request,
pageable, moderationRequests, SW360Constants.TYPE_MODERATION, totalCount);

List<EntityModel<ModerationRequest>> moderationRequestResources = new ArrayList<>();
paginationResult.getResources().forEach(m -> addModerationRequest(m, allDetails, moderationRequestResources));

CollectionModel<ModerationRequest> resources;
if (moderationRequestResources.isEmpty()) {
resources = restControllerHelper.emptyPageResource(ModerationRequest.class, paginationResult);
} else {
resources = restControllerHelper.generatePagesResource(paginationResult, moderationRequestResources);
}
Map<PaginationData, List<ModerationRequest>> modRequestsWithPageData =
new HashMap<>();
PaginationData paginationData = new PaginationData();
paginationData.setTotalRowCount(sw360ModerationRequestService.getTotalCountOfRequests(sw360User));
modRequestsWithPageData.put(paginationData, moderationRequests);

HttpStatus status = resources == null ? HttpStatus.NO_CONTENT : HttpStatus.OK;
return new ResponseEntity<>(resources, status);
return getModerationResponseEntity(pageable, request, allDetails, modRequestsWithPageData);
}

@Operation(
Expand Down Expand Up @@ -166,27 +158,7 @@ public ResponseEntity<CollectionModel<ModerationRequest>> getModerationRequestsB
boolean stateOpen = stateOptions.get(0).equalsIgnoreCase(state);
Map<PaginationData, List<ModerationRequest>> modRequestsWithPageData =
sw360ModerationRequestService.getRequestsByState(sw360User, pageable, stateOpen, allDetails);
List<ModerationRequest> moderationRequests = new ArrayList<>();
int totalCount = 0;
if (!CommonUtils.isNullOrEmptyMap(modRequestsWithPageData)) {
PaginationData paginationData = modRequestsWithPageData.keySet().iterator().next();
moderationRequests = modRequestsWithPageData.get(paginationData);
totalCount = (int) paginationData.getTotalRowCount();
}

PaginationResult<ModerationRequest> paginationResult = restControllerHelper.paginationResultFromPaginatedList(request,
pageable, moderationRequests, SW360Constants.TYPE_MODERATION, totalCount);

List<EntityModel<ModerationRequest>> moderationRequestResources = new ArrayList<>();
paginationResult.getResources().forEach(m -> addModerationRequest(m, allDetails, moderationRequestResources));

CollectionModel<ModerationRequest> resources;
if (moderationRequestResources.isEmpty()) {
resources = restControllerHelper.emptyPageResource(ModerationRequest.class, paginationResult);
} else {
resources = restControllerHelper.generatePagesResource(paginationResult, moderationRequestResources);
}
return new ResponseEntity<>(resources, HttpStatus.OK);
return getModerationResponseEntity(pageable, request, allDetails, modRequestsWithPageData);
}

private @NotNull HalResource<ModerationRequest> createHalModerationRequestWithAllDetails(
Expand Down Expand Up @@ -317,4 +289,57 @@ private void addModerationRequest(ModerationRequest moderationRequest, boolean a
}
moderationRequestResources.add(embeddedModerationRequestResource);
}

@Operation(
summary = "Get my submissions.",
description = "Get moderation requests submitted by the user. The responses are sortable by fields " +
"\"timestamp\", \"documentName\" and \"moderationState\".",
tags = {"Moderation Requests"}
)
@GetMapping(value = MODERATION_REQUEST_URL + "/mySubmissions")
public ResponseEntity<CollectionModel<ModerationRequest>> getSubmissions(
Pageable pageable, HttpServletRequest request
) throws TException, URISyntaxException, ResourceClassNotFoundException {
User sw360User = restControllerHelper.getSw360UserFromAuthentication();
Map<PaginationData, List<ModerationRequest>> modRequestsWithPageData =
sw360ModerationRequestService.getRequestsByRequestingUser(sw360User, pageable);
return getModerationResponseEntity(pageable, request, false, modRequestsWithPageData);
}

/**
* Generate a Response Entity for paginated moderation request list.
* @param pageable Pageable request
* @param request HTTP Request
* @param allDetails Request with allDetails?
* @param modRequestsWithPageData Map of pagination data and moderation request list
* @return Returns the Response Entity with pagination data.
*/
@NotNull
private ResponseEntity<CollectionModel<ModerationRequest>> getModerationResponseEntity(
Pageable pageable, HttpServletRequest request, boolean allDetails,
Map<PaginationData, List<ModerationRequest>> modRequestsWithPageData
) throws ResourceClassNotFoundException, URISyntaxException {
List<ModerationRequest> moderationRequests = new ArrayList<>();
int totalCount = 0;
if (!CommonUtils.isNullOrEmptyMap(modRequestsWithPageData)) {
PaginationData paginationData = modRequestsWithPageData.keySet().iterator().next();
moderationRequests = modRequestsWithPageData.get(paginationData);
totalCount = (int) paginationData.getTotalRowCount();
}

PaginationResult<ModerationRequest> paginationResult = restControllerHelper.paginationResultFromPaginatedList(
request, pageable, moderationRequests, SW360Constants.TYPE_MODERATION, totalCount);

List<EntityModel<ModerationRequest>> moderationRequestResources = new ArrayList<>();
paginationResult.getResources().forEach(m -> addModerationRequest(m, allDetails, moderationRequestResources));

CollectionModel<ModerationRequest> resources;
if (moderationRequestResources.isEmpty()) {
resources = restControllerHelper.emptyPageResource(ModerationRequest.class, paginationResult);
} else {
resources = restControllerHelper.generatePagesResource(paginationResult, moderationRequestResources);
}
HttpStatus status = resources == null ? HttpStatus.NO_CONTENT : HttpStatus.OK;
return new ResponseEntity<>(resources, status);
}
}
Loading

0 comments on commit ed7e431

Please sign in to comment.