Merge branch 'feature/red-9393' into 'master'
RED-9393: user stats endpoint See merge request redactmanager/persistence-service!789
This commit is contained in:
commit
f6caa94136
@ -0,0 +1,54 @@
|
||||
package com.iqser.red.persistence.service.v1.external.api.impl.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.iqser.red.service.persistence.management.v1.processor.acl.custom.dossier.DossierACLService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.DossierService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.users.UserService;
|
||||
import com.iqser.red.service.persistence.service.v1.api.external.resource.UserStatsResource;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.UserStats;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class UserStatsController implements UserStatsResource {
|
||||
|
||||
private final UserService userService;
|
||||
private final DossierService dossierService;
|
||||
private final FileStatusPersistenceService fileStatusPersistenceService;
|
||||
private final DossierACLService dossierACLService;
|
||||
|
||||
|
||||
@Override
|
||||
public ResponseEntity<UserStats> getUserStats(String userId) {
|
||||
|
||||
if (userService.getUserById(userId).isEmpty()) {
|
||||
return new ResponseEntity(null, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
List<String> dossierMemberships = new ArrayList<>();
|
||||
List<String> dossierOwnerships = new ArrayList<>();
|
||||
dossierService.getAllDossiers()
|
||||
.stream()
|
||||
.forEach(d -> {
|
||||
if (dossierACLService.getMembers(d.getId()).contains(userId)) {
|
||||
dossierMemberships.add(d.getId());
|
||||
}
|
||||
if (dossierACLService.getOwners(d.getId()).contains(userId)) {
|
||||
dossierOwnerships.add(d.getId());
|
||||
}
|
||||
});
|
||||
|
||||
return new ResponseEntity<>(new UserStats(dossierMemberships.size(), dossierOwnerships.size(), this.fileStatusPersistenceService.getNumberOfAssignedFiles(userId)),
|
||||
HttpStatus.OK);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.external.resource;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.UserStats;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "429", description = "Too many requests.")})
|
||||
public interface UserStatsResource {
|
||||
|
||||
String USER_ID_PARAM = "userId";
|
||||
|
||||
String USER_ID_PATH_VARIABLE = "/{" + USER_ID_PARAM + "}";
|
||||
|
||||
String STATS_PATH = "/user-stats";
|
||||
|
||||
String PATH = ExternalApi.BASE_PATH + STATS_PATH;
|
||||
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@ResponseBody
|
||||
@GetMapping(value = PATH + USER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Gets user stats for user specified by id.", description = "")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not found")})
|
||||
ResponseEntity<UserStats> getUserStats(@Parameter(name = USER_ID_PARAM, description = "The unique identifier of the user whose statistics we want to retrieve.", required = true) @PathVariable(USER_ID_PARAM) String userId);
|
||||
|
||||
}
|
||||
@ -73,6 +73,24 @@ public class DossierACLService extends AbstractACLService<String> {
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getOwners(String dossierId) {
|
||||
|
||||
ObjectIdentityImpl dossierIdentity = new ObjectIdentityImpl(getIdentifier(), dossierId);
|
||||
var acl = mutableAclService.readAclById(dossierIdentity);
|
||||
Set<String> members = new HashSet<>();
|
||||
acl.getEntries()
|
||||
.forEach(entry -> {
|
||||
if (entry.getSid() instanceof PrincipalSid) {
|
||||
var principal = ((PrincipalSid) entry.getSid()).getPrincipal();
|
||||
if (entry.getPermission().getMask() == RedPermission.OWNER.getMask()) {
|
||||
members.add(principal);
|
||||
}
|
||||
}
|
||||
});
|
||||
return members;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
|
||||
|
||||
@ -168,6 +168,10 @@ public final class ActionRoles {
|
||||
public static final String READ_APP_CONFIG = "red-read-app-configuration";
|
||||
public static final String WRITE_APP_CONFIG = "red-write-app-configuration";
|
||||
|
||||
// USER STATS
|
||||
|
||||
public static final String READ_USER_STATS = "red-get-user-stats";
|
||||
|
||||
// License Management
|
||||
public static final String UPDATE_LICENSE = "red-update-license";
|
||||
public static final String READ_LICENSE = "red-read-license";
|
||||
|
||||
@ -10,7 +10,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.projection.DossierStatsFileProjection;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -18,14 +17,15 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileAttributeEntity;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntityComponentMappingVersionEntity;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.projection.DossierStatsFileProjection;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.model.FileIdentifier;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.model.OCRStatusUpdateResponse;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.model.websocket.AnalyseStatus;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileAttributesRepository;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttribute;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentMappingMetadata;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo;
|
||||
@ -415,6 +415,7 @@ public class FileStatusPersistenceService {
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
public List<FileEntity> getActiveFilesForDossierTemplate(String dossierTemplateId) {
|
||||
|
||||
return dossierService.findAllActiveDossiersForDossierTemplateId(dossierTemplateId)
|
||||
@ -440,6 +441,7 @@ public class FileStatusPersistenceService {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
public List<DossierStatsFileProjection> getFilesForDossierStats(String dossierId) {
|
||||
|
||||
return fileRepository.findDossierStatsProjectionFileProjectionByDossierId(dossierId);
|
||||
@ -500,12 +502,12 @@ public class FileStatusPersistenceService {
|
||||
fileAttributesRepository.deleteByFileIds(fileIds);
|
||||
}
|
||||
|
||||
|
||||
public void hardDeleteFiles(List<String> fileIds, OffsetDateTime hardDeleteTime) {
|
||||
|
||||
fileRepository.hardDeleteFiles(fileIds, ProcessingStatus.PROCESSED, hardDeleteTime);
|
||||
fileAttributesRepository.deleteByFileIds(fileIds);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -573,7 +575,8 @@ public class FileStatusPersistenceService {
|
||||
uploader,
|
||||
ProcessingStatus.UNPROCESSED,
|
||||
OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS),
|
||||
OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), disableAutomaticAnalysis);
|
||||
OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS),
|
||||
disableAutomaticAnalysis);
|
||||
} else {
|
||||
|
||||
fileRepository.findById(fileId)
|
||||
@ -585,7 +588,8 @@ public class FileStatusPersistenceService {
|
||||
ProcessingStatus.UNPROCESSED,
|
||||
WorkflowStatus.NEW,
|
||||
OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS),
|
||||
OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS), disableAutomaticAnalysis);
|
||||
OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS),
|
||||
disableAutomaticAnalysis);
|
||||
deleteFileAttributes(fileId);
|
||||
}
|
||||
|
||||
@ -595,6 +599,13 @@ public class FileStatusPersistenceService {
|
||||
}
|
||||
|
||||
|
||||
public int getNumberOfAssignedFiles(String userId) {
|
||||
|
||||
List<FileEntity> files = fileRepository.findFilesByAssignee(userId);
|
||||
return files.size();
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void deleteFileAttributes(String fileId) {
|
||||
|
||||
@ -647,11 +658,14 @@ public class FileStatusPersistenceService {
|
||||
fileRepository.updateFileModificationDate(fileId, fileManipulationDate);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void resetErrorCounter(String dossierTemplateId){
|
||||
public void resetErrorCounter(String dossierTemplateId) {
|
||||
|
||||
fileRepository.updateErrorCounter(dossierTemplateId, 0);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void updateHasHighlights(String fileId, boolean hasHighlights) {
|
||||
|
||||
@ -726,7 +740,7 @@ public class FileStatusPersistenceService {
|
||||
|
||||
public List<String> findAllByDossierId(String dossierId, boolean includeDeleted) {
|
||||
|
||||
return fileRepository.findAllByDossierId(dossierId, includeDeleted);
|
||||
return fileRepository.findAllByDossierId(dossierId, includeDeleted);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -49,6 +49,10 @@ public interface FileRepository extends JpaRepository<FileEntity, String> {
|
||||
@Param("hasUpdates") boolean hasUpdates);
|
||||
|
||||
|
||||
@Query("select f from FileEntity f where f.assignee = :assignee")
|
||||
List<FileEntity> findFilesByAssignee(@Param("assignee") String assignee);
|
||||
|
||||
|
||||
@Modifying
|
||||
@Query("""
|
||||
update FileEntity f set f.numberOfPages = :numberOfPages, \
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserStats {
|
||||
|
||||
private int numberOfDossierMemberships;
|
||||
private int numberOfDossierOwnerships;
|
||||
private int numberOfAssignedFiles;
|
||||
public UserStats(int numberOfDossierMemberships, int numberOfDossierOwnerships, int numberOfAssignedFiles) {
|
||||
|
||||
this.numberOfDossierMemberships = numberOfDossierMemberships;
|
||||
this.numberOfDossierOwnerships = numberOfDossierOwnerships;
|
||||
this.numberOfAssignedFiles = numberOfAssignedFiles;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user