RED-9393: user stats endpoint

added endpoint with discussed path
This commit is contained in:
yhampe 2024-10-23 09:10:11 +02:00
parent 48a7d05ba1
commit c21a97420d
7 changed files with 144 additions and 0 deletions

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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() {

View File

@ -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";

View File

@ -18,6 +18,7 @@ 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;
@ -26,6 +27,7 @@ import com.iqser.red.service.persistence.management.v1.processor.model.websocket
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;
@ -595,6 +597,13 @@ public class FileStatusPersistenceService {
}
public int getNumberOfAssignedFiles(String userId) {
List<FileEntity> files = fileRepository.findFilesByAssignee(userId);
return files.size();
}
@Transactional
public void deleteFileAttributes(String fileId) {

View File

@ -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, \

View File

@ -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;
}
}