Compare commits

..

2 Commits

Author SHA1 Message Date
Ali Oezyetimoglu
f6030f61de RED-10730: added logs 2025-01-22 07:08:43 +01:00
Ali Oezyetimoglu
4fb19f14a9 RED-10730: added internal endpoints for dossier-initialization-service 2025-01-21 20:22:25 +01:00
13 changed files with 402 additions and 97 deletions

View File

@ -28,7 +28,6 @@ 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.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.exception.ConflictException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotAllowedException;
import com.iqser.red.service.persistence.management.v1.processor.roles.ApplicationRoles;
import com.iqser.red.service.persistence.management.v1.processor.service.AccessControlService;
@ -102,13 +101,8 @@ public class StatusController implements StatusResource {
var accessibleDossierIds = filterByPermissionsService.onlyViewableDossierIds(new ArrayList<>(filesByDossier.getValue().keySet()));
var response = new HashMap<String, List<FileStatus>>();
for (var dossierId : accessibleDossierIds) {
var allFoundFiles = fileStatusManagementService.findAllDossierIdAndIds(dossierId,
filesByDossier.getValue()
.get(dossierId));
response.put(dossierId,
allFoundFiles.stream()
.map(FileStatusMapper::toFileStatus)
.collect(Collectors.toList()));
var allFoundFiles = fileStatusManagementService.findAllDossierIdAndIds(dossierId, filesByDossier.getValue().get(dossierId));
response.put(dossierId, allFoundFiles.stream().map(FileStatusMapper::toFileStatus).collect(Collectors.toList()));
}
return new JSONPrimitive<>(response);
@ -357,10 +351,6 @@ public class StatusController implements StatusResource {
.build());
var dossier = dossierACLService.enhanceDossierWithACLData(dossierManagementService.getDossierById(dossierId, false, false));
if (dossier.getOwnerId() == null) {
throw new ConflictException("Dossier has no owner!");
}
if (!dossier.getOwnerId().equals(KeycloakSecurity.getUserId())) {
var fileStatus = fileStatusManagementService.getFileStatus(fileId);

View File

@ -2,17 +2,18 @@ package com.iqser.red.service.persistence.v1.internal.api.controller;
import java.util.List;
import jakarta.transaction.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.persistence.management.v1.processor.service.DossierManagementService;
import com.iqser.red.service.persistence.service.v1.api.internal.resources.DossierResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.CreateOrUpdateDossierRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
import feign.Param;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -42,4 +43,12 @@ public class DossierInternalController implements DossierResource {
return dossierManagementService.getDossierById(dossierId, includeArchived, includeDeleted);
}
@Override
@Transactional
public Dossier createDossier(@RequestBody CreateOrUpdateDossierRequest dossierRequest) {
return dossierManagementService.createDossier(dossierRequest);
}
}

View File

@ -2,6 +2,8 @@ package com.iqser.red.service.persistence.v1.internal.api.controller;
import static com.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter.convert;
import java.util.List;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@ -37,4 +39,11 @@ public class DossierTemplateInternalController implements DossierTemplateResourc
return convert(dossierTemplatePersistenceService.getDossierTemplate(dossierTemplateId), DossierTemplate.class);
}
@Override
public List<DossierTemplate> getAllDossierTemplates() {
return convert(dossierTemplatePersistenceService.getAllDossierTemplates(), DossierTemplate.class);
}
}

View File

@ -0,0 +1,35 @@
package com.iqser.red.service.persistence.v1.internal.api.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.iqser.red.service.persistence.management.v1.processor.service.UploadManagementService;
import com.iqser.red.service.persistence.service.v1.api.internal.resources.UploadResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileUploadResult;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@RestController
@RequiredArgsConstructor
@Slf4j
@SuppressWarnings("PMD")
public class UploadInternalController implements UploadResource {
private final UploadManagementService uploadManagementService;
@Override
public FileUploadResult upload(@RequestPart(name = "file") MultipartFile file,
@PathVariable(DOSSIER_ID) String dossierId,
@RequestParam(value = "keepManualRedactions", required = false, defaultValue = "false") boolean keepManualRedactions,
@Parameter(name = DISABLE_AUTOMATIC_ANALYSIS_PARAM, description = "Disables automatic redaction for the uploaded file, imports only imported redactions") @RequestParam(value = DISABLE_AUTOMATIC_ANALYSIS_PARAM, required = false, defaultValue = "false") boolean disableAutomaticAnalysis) {
return uploadManagementService.upload(file, dossierId, keepManualRedactions, disableAutomaticAnalysis);
}
}

View File

@ -6,9 +6,13 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
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.dossiertemplate.dossier.CreateOrUpdateDossierRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
@ResponseStatus(value = HttpStatus.OK)
@ -33,4 +37,9 @@ public interface DossierResource {
@RequestParam(name = INCLUDE_ARCHIVED_PARAM, defaultValue = "false", required = false) boolean includeArchived,
@RequestParam(name = INCLUDE_DELETED_PARAM, defaultValue = "false", required = false) boolean includeDeleted);
@ResponseBody
@PostMapping(value = InternalApi.BASE_PATH + REST_PATH, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
Dossier createDossier(@RequestBody CreateOrUpdateDossierRequest dossierRequest);
}

View File

@ -1,5 +1,7 @@
package com.iqser.red.service.persistence.service.v1.api.internal.resources;
import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -29,4 +31,8 @@ public interface DossierTemplateResource {
@GetMapping(value = InternalApi.BASE_PATH + DOSSIER_TEMPLATE_PATH + DOSSIER_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE)
DossierTemplate getDossierTemplateById(@PathVariable(DOSSIER_TEMPLATE_ID_PARAM) String dossierTemplateId);
@GetMapping(value = InternalApi.BASE_PATH + DOSSIER_TEMPLATE_PATH, produces = MediaType.APPLICATION_JSON_VALUE)
List<DossierTemplate> getAllDossierTemplates();
}

View File

@ -0,0 +1,33 @@
package com.iqser.red.service.persistence.service.v1.api.internal.resources;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileUploadResult;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
public interface UploadResource {
String DOSSIER_ID = "dossierId";
String FILE_ID = "fileId";
String UPLOAD_PATH = InternalApi.BASE_PATH + "/upload";
String DOSSIER_ID_PATH_VARIABLE = "/{" + DOSSIER_ID + "}";
String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}";
String DISABLE_AUTOMATIC_ANALYSIS_PARAM = "disableAutomaticAnalysis";
@ResponseBody
@PostMapping(value = UPLOAD_PATH + DOSSIER_ID_PATH_VARIABLE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
FileUploadResult upload(@Schema(type = "string", format = "binary", name = "file") @RequestPart(name = "file") MultipartFile file,
@PathVariable(DOSSIER_ID) String dossierId,
@RequestParam(value = "keepManualRedactions", required = false, defaultValue = "false") boolean keepManualRedactions,
@Parameter(name = DISABLE_AUTOMATIC_ANALYSIS_PARAM, description = "Disables automatic analysis for the uploaded file, imports only imported redactions") @RequestParam(value = DISABLE_AUTOMATIC_ANALYSIS_PARAM, required = false, defaultValue = "false") boolean disableAutomaticAnalysis);
}

View File

@ -1,5 +1,16 @@
package com.iqser.red.service.persistence.management.v1.processor.service;
import static com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException.DOSSIER_NOT_FOUND_MESSAGE;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.utils.DossierMapper;
@ -17,17 +28,6 @@ import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException.DOSSIER_NOT_FOUND_MESSAGE;
@Slf4j
@Service
@RequiredArgsConstructor
@ -47,6 +47,13 @@ public class DossierManagementService {
}
@Transactional
public Dossier createDossier(CreateOrUpdateDossierRequest dossierRequest) {
return MagicConverter.convert(dossierService.addDossier(dossierRequest), Dossier.class, new DossierMapper());
}
@Transactional
public Dossier updateDossier(CreateOrUpdateDossierRequest dossierRequest, String dossierId) {
@ -65,8 +72,9 @@ public class DossierManagementService {
List<FileModel> fileStatuses = fileStatusService.getDossierStatus(dossierId);
var relevantFileIds = fileStatuses.stream()
.filter(fileStatus -> fileStatus.getDeleted() == null).map(FileModel::getId).toList();
.filter(fileStatus -> fileStatus.getDeleted() == null)
.map(FileModel::getId)
.toList();
dossierDeletionService.softDeleteDossier(dossierId, relevantFileIds, now);
fileDeletionService.reindexDeletedFiles(dossierId, relevantFileIds);
@ -120,12 +128,14 @@ public class DossierManagementService {
}
@Transactional
public List<String> getAllDossierIdsForDossierTemplateId(String dossierTemplateId, boolean includeArchived, boolean includeDeleted) {
return dossierService.getAllDossierIdsForDossierTemplateId(dossierTemplateId, includeArchived, includeDeleted);
}
@Transactional
public List<String> findAllDossierIdsInDossierTemplateId(String dossierTemplateId, Set<String> dossierIds) {
@ -215,7 +225,10 @@ public class DossierManagementService {
for (String dossierId : dossierIds) {
List<String> fileIds = fileStatusService.getDossierStatus(dossierId).stream().map(FileModel::getId).collect(Collectors.toList());
List<String> fileIds = fileStatusService.getDossierStatus(dossierId)
.stream()
.map(FileModel::getId)
.collect(Collectors.toList());
dossierDeletionService.hardDeleteDossier(dossierId, fileIds);
dossierDeletionService.hardDeleteFileDataAndIndexUpdates(dossierId, fileIds);
}
@ -228,10 +241,13 @@ public class DossierManagementService {
for (String dossierId : dossierIds) {
var dossier = dossierService.getDossierById(dossierId);
List<FileModel> fileStatuses = fileStatusService.getDossierStatus(dossierId);
var relevantFileIds = fileStatuses.stream().filter(fileStatus -> fileStatus.getDeleted() != null && (fileStatus.getDeleted().equals(dossier.getSoftDeletedTime()) || fileStatus.getDeleted()
.isAfter(dossier.getSoftDeletedTime()))).map(FileModel::getId).collect(Collectors.toList());
var relevantFileIds = fileStatuses.stream()
.filter(fileStatus -> fileStatus.getDeleted() != null && (fileStatus.getDeleted().equals(dossier.getSoftDeletedTime()) || fileStatus.getDeleted()
.isAfter(dossier.getSoftDeletedTime())))
.map(FileModel::getId)
.collect(Collectors.toList());
dossierDeletionService.undeleteDossier(dossierId,relevantFileIds,dossier.getSoftDeletedTime());
dossierDeletionService.undeleteDossier(dossierId, relevantFileIds, dossier.getSoftDeletedTime());
dossierDeletionService.reindexUndeletedFiles(dossier.getDossierTemplateId(), dossierId, relevantFileIds);
}
@ -278,6 +294,7 @@ public class DossierManagementService {
public DossierChangeResponseV2 changesSinceV2(JSONPrimitive<OffsetDateTime> since) {
return dossierService.changesSinceV2(since.getValue());
}
@ -285,7 +302,7 @@ public class DossierManagementService {
@Transactional
public List<Dossier> getDossiersByIds(Set<String> viewableDossierIds) {
return getConvertedAllDossiers(dossierService.getAllDossiers(viewableDossierIds), true,true);
return getConvertedAllDossiers(dossierService.getAllDossiers(viewableDossierIds), true, true);
}
}

View File

@ -59,6 +59,7 @@ public class DossierService {
validateDossierName(createOrUpdateDossierRequest);
try {
log.info("PSPS: " + createOrUpdateDossierRequest);
return dossierPersistenceService.insert(createOrUpdateDossierRequest);
} catch (Exception e) {
if (e.getCause() instanceof ConstraintViolationException) {

View File

@ -0,0 +1,254 @@
package com.iqser.red.service.persistence.management.v1.processor.service;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;
import java.util.UUID;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotAllowedException;
import com.iqser.red.service.persistence.management.v1.processor.utils.FileUtils;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileUploadResult;
import com.knecon.fforesight.tenantcommons.TenantContext;
import io.micrometer.core.annotation.Timed;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
@RequiredArgsConstructor
public class UploadManagementService {
private static final int THRESHOLD_ENTRIES = 10000; // Maximum number of files allowed
private static final int THRESHOLD_SIZE = 1000000000; // 1 GB total unzipped data
private static final double THRESHOLD_RATIO = 10; // Max allowed compression ratio
private final UploadService uploadService;
private final AccessControlService accessControlService;
private final FileFormatValidationService fileFormatValidationService;
@Timed
public FileUploadResult upload(MultipartFile file, String dossierId, boolean keepManualRedactions, boolean disableAutomaticAnalysis) {
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
throw new BadRequestException("Could not upload file, no filename provided.");
}
String extension = getExtension(originalFilename);
try {
return switch (extension) {
case "zip" -> handleZip(dossierId, file.getBytes(), keepManualRedactions, disableAutomaticAnalysis);
case "csv" -> uploadService.importCsv(dossierId, file.getBytes());
default -> {
validateExtensionOrThrow(extension);
yield uploadService.processSingleFile(dossierId, originalFilename, file.getBytes(), keepManualRedactions, disableAutomaticAnalysis);
}
};
} catch (IOException e) {
throw new BadRequestException("Failed to process file: " + e.getMessage(), e);
}
}
private void validateExtensionOrThrow(String extension) {
if (!fileFormatValidationService.getAllFileFormats().contains(extension)) {
throw new BadRequestException("Invalid file uploaded (unrecognized extension).");
}
if (!fileFormatValidationService.getValidFileFormatsForTenant(TenantContext.getTenantId()).contains(extension)) {
throw new NotAllowedException("Insufficient permissions for this file type.");
}
}
/**
* 1. Write the uploaded content to a temp ZIP file
* 2. Check the number of entries and reject if too big or if symlinks found
* 3. Unzip and process each file, while checking size and ratio.
*/
private FileUploadResult handleZip(String dossierId, byte[] fileContent, boolean keepManualRedactions, boolean disableAutomaticAnalysis) throws IOException {
File tempZip = FileUtils.createTempFile(UUID.randomUUID().toString(), ".zip");
try (FileOutputStream fos = new FileOutputStream(tempZip)) {
IOUtils.write(fileContent, fos);
}
validateZipEntries(tempZip);
try {
ZipData zipData = processZipContents(tempZip, dossierId, keepManualRedactions, disableAutomaticAnalysis);
if (zipData.csvBytes != null) {
try {
FileUploadResult csvResult = uploadService.importCsv(dossierId, zipData.csvBytes);
zipData.fileUploadResult.getProcessedAttributes().addAll(csvResult.getProcessedAttributes());
zipData.fileUploadResult.getProcessedFileIds().addAll(csvResult.getProcessedFileIds());
} catch (Exception e) {
log.debug("CSV file inside ZIP failed to import", e);
}
} else if (zipData.fileUploadResult.getFileIds().isEmpty()) {
if (zipData.containedUnpermittedFiles) {
throw new NotAllowedException("Zip file contains unpermitted files.");
} else {
throw new BadRequestException("Only unsupported files in the ZIP.");
}
}
return zipData.fileUploadResult;
} finally {
if (!tempZip.delete()) {
log.warn("Could not delete temporary ZIP file: {}", tempZip);
}
}
}
private void validateZipEntries(File tempZip) throws IOException {
try (FileInputStream fis = new FileInputStream(tempZip); ZipFile zipFile = new ZipFile(fis.getChannel())) {
int count = 0;
var entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry ze = entries.nextElement();
if (ze.isUnixSymlink()) {
throw new BadRequestException("ZIP-files with symlinks are not allowed.");
}
if (!ze.isDirectory() && !ze.getName().startsWith(".")) {
count++;
if (count > THRESHOLD_ENTRIES) {
throw new BadRequestException("ZIP-Bomb detected: too many entries.");
}
}
}
}
}
private ZipData processZipContents(File tempZip, String dossierId, boolean keepManualRedactions, boolean disableAutomaticAnalysis) throws IOException {
ZipData zipData = new ZipData();
try (FileInputStream fis = new FileInputStream(tempZip); ZipFile zipFile = new ZipFile(fis.getChannel())) {
var entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
if (entry.isDirectory() || entry.getName().startsWith(".")) {
continue;
}
byte[] entryBytes = readEntryWithRatioCheck(entry, zipFile);
zipData.totalSizeArchive += entryBytes.length;
if (zipData.totalSizeArchive > THRESHOLD_SIZE) {
throw new BadRequestException("ZIP-Bomb detected (exceeds total size limit).");
}
String extension = getExtension(entry.getName());
if ("csv".equalsIgnoreCase(extension)) {
zipData.csvBytes = entryBytes;
} else {
handleRegularFile(dossierId, entryBytes, extension, extractFileName(entry.getName()), zipData, keepManualRedactions, disableAutomaticAnalysis);
}
}
}
return zipData;
}
private byte[] readEntryWithRatioCheck(ZipArchiveEntry entry, ZipFile zipFile) throws IOException {
long compressedSize = entry.getCompressedSize() > 0 ? entry.getCompressedSize() : 1;
try (var is = zipFile.getInputStream(entry); var bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
int totalUncompressed = 0;
while ((bytesRead = is.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
totalUncompressed += bytesRead;
double ratio = (double) totalUncompressed / compressedSize;
if (ratio > THRESHOLD_RATIO) {
throw new BadRequestException("ZIP-Bomb detected (compression ratio too high).");
}
}
return bos.toByteArray();
}
}
private void handleRegularFile(String dossierId,
byte[] fileBytes,
String extension,
String fileName,
ZipData zipData,
boolean keepManualRedactions,
boolean disableAutomaticAnalysis) {
if (!fileFormatValidationService.getAllFileFormats().contains(extension)) {
zipData.containedUnpermittedFiles = false;
return;
}
if (!fileFormatValidationService.getValidFileFormatsForTenant(TenantContext.getTenantId()).contains(extension)) {
zipData.containedUnpermittedFiles = true;
return;
}
try {
FileUploadResult result = uploadService.processSingleFile(dossierId, fileName, fileBytes, keepManualRedactions, disableAutomaticAnalysis);
zipData.fileUploadResult.getFileIds().addAll(result.getFileIds());
} catch (Exception e) {
log.debug("Failed to process file '{}' in ZIP: {}", fileName, e.getMessage(), e);
}
}
private String extractFileName(String path) {
int idx = path.lastIndexOf('/');
return (idx >= 0) ? path.substring(idx + 1) : path;
}
private String getExtension(String fileName) {
int idx = fileName.lastIndexOf('.');
if (idx < 0) {
return "";
}
return fileName.substring(idx + 1).toLowerCase(Locale.ROOT);
}
@FieldDefaults(level = AccessLevel.PUBLIC)
private static final class ZipData {
byte[] csvBytes;
int totalSizeArchive;
FileUploadResult fileUploadResult = new FileUploadResult();
boolean containedUnpermittedFiles;
}
}

View File

@ -142,8 +142,7 @@ fforesight:
ignored-endpoints: [ '/redaction-gateway-v1', '/actuator/health/**',"/redaction-gateway-v1/websocket","/redaction-gateway-v1/websocket/**", '/redaction-gateway-v1/async/download/with-ott/**',
'/internal-api/**', '/redaction-gateway-v1/docs/swagger-ui',
'/redaction-gateway-v1/docs/**','/redaction-gateway-v1/docs',
'/api', '/api/','/api/docs/**','/api/docs','/api/docs/swagger-ui',
'/actuator/prometheus']
'/api', '/api/','/api/docs/**','/api/docs','/api/docs/swagger-ui' ]
enabled: true
springdoc:
base-path: '/api'

View File

@ -1,18 +1,13 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.junit.Assert.assertThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
@ -23,8 +18,8 @@ import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.management.v1.processor.acl.custom.dossier.DossierACLService;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
@ -38,8 +33,6 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemp
import com.iqser.red.service.persistence.service.v1.api.shared.model.warning.ApproveResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.warning.WarningType;
import feign.FeignException;
public class ApprovalTest extends AbstractPersistenceServerServiceTest {
@Autowired
@ -51,15 +44,15 @@ public class ApprovalTest extends AbstractPersistenceServerServiceTest {
@Autowired
private DossierTesterAndProvider dossierTesterAndProvider;
@Autowired
private TypeProvider typeProvider;
@Autowired
private FileClient fileClient;
@SpyBean
private LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
@SpyBean
private DossierACLService dossierACLService;
@Test
public void testApprovalNoWarnings() {
@ -188,54 +181,4 @@ public class ApprovalTest extends AbstractPersistenceServerServiceTest {
assertTrue(approveResponse.getFileWarnings().isEmpty());
}
@Test
void testApprovalWhenDossierHasNoOwner() {
DossierTemplateModel dossierTemplateModel = dossierTemplateTesterAndProvider.provideTestTemplate();
Dossier dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplateModel);
FileStatus file = fileTesterAndProvider.testAndProvideFile(dossier, "some-file");
fileTesterAndProvider.markFileAsProcessed(dossier.getId(), file.getFileId());
EntityLog entityLog = new EntityLog();
when(entityLogService.getEntityLog(anyString(), anyString(), anyBoolean())).thenReturn(entityLog);
List<com.iqser.red.service.persistence.management.v1.processor.service.users.model.User> allUsers = new ArrayList<>();
allUsers.add(com.iqser.red.service.persistence.management.v1.processor.service.users.model.User.builder()
.userId("manageradmin1@test.com")
.email("manageradmin1@test.com")
.isActive(true)
.roles(Set.of(getAllRoles()))
.build());
allUsers.add(com.iqser.red.service.persistence.management.v1.processor.service.users.model.User.builder()
.userId("manageradmin2@test.com")
.email("manageradmin2@test.com")
.isActive(true)
.roles(Set.of("RED_USER"))
.build());
when(usersClient.getAllUsers(false)).thenReturn(allUsers);
when(usersClient.getAllUsers(true)).thenReturn(allUsers);
doAnswer(invocation -> {
Dossier arg = invocation.getArgument(0);
if (dossier.getId().equals(arg.getId())) {
Dossier emptyDossier = new Dossier();
emptyDossier.setId(arg.getId());
return emptyDossier;
} else {
return invocation.callRealMethod();
}
}).when(dossierACLService).enhanceDossierWithACLData(any(Dossier.class));
FeignException ex = assertThrows(FeignException.Conflict.class, () -> {
fileClient.setStatusApproved(dossier.getId(), file.getFileId(), false);
});
assertTrue(ex.getMessage().contains("Dossier has no owner!"));
}
}

View File

@ -261,7 +261,7 @@ public abstract class AbstractPersistenceServerServiceTest {
@MockBean
protected TenantsClient tenantsClient;
@MockBean
protected UsersClient usersClient;
private UsersClient usersClient;
@Autowired
protected EncryptionDecryptionService encryptionDecryptionService;
@Autowired
@ -286,7 +286,7 @@ public abstract class AbstractPersistenceServerServiceTest {
private CurrentApplicationTypeProvider currentApplicationTypeProvider;
protected static String[] getAllRoles() {
private static String[] getAllRoles() {
var allRoles = ApplicationRoles.ROLE_DATA.entrySet()
.stream()