RED-9868 - Import older template zip with incompatible component rules breaks the stack - bp #663

Merged
corina.olariu.ext1 merged 3 commits from RED-9868-bp into release/2.465.x 2024-08-15 09:19:56 +02:00
9 changed files with 94 additions and 26 deletions

View File

@ -23,6 +23,7 @@ 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.FileUploadException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.service.RulesValidationService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.RulesPersistenceService;
@ -99,8 +100,11 @@ public class RulesController implements RulesResource {
@PreAuthorize("hasAuthority('" + READ_RULES + "')")
public RulesResponse download(@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId, @PathVariable(RULE_FILE_TYPE_PARAMETER_NAME) RuleFileType ruleFileType) {
var ruleEntity = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
return new RulesResponse(ruleEntity.getValue(), dossierTemplateId, ruleEntity.isTimeoutDetected());
var ruleEntityOptional = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
if (ruleEntityOptional.isEmpty()) {
throw new NotFoundException(String.format("No rule file of type %s found for dossierTemplateId %s", ruleFileType, dossierTemplateId));
}
return new RulesResponse(ruleEntityOptional.get().getValue(), dossierTemplateId, ruleEntityOptional.get().isTimeoutDetected());
}

View File

@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
@ -39,6 +40,7 @@ import com.iqser.red.persistence.service.v2.external.api.impl.mapper.ComponentMa
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.RuleSetEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.ComponentDefinitionEntity;
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.ComponentMappingDownloadModel;
import com.iqser.red.service.persistence.management.v1.processor.service.ComponentDefinitionService;
import com.iqser.red.service.persistence.management.v1.processor.service.ComponentMappingService;
@ -507,9 +509,11 @@ public class DossierTemplateControllerV2 implements DossierTemplateResource {
private ResponseEntity<?> downloadRules(String dossierTemplateId, RuleFileType ruleFileType) {
RuleSetEntity ruleEntity = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
var data = ruleEntity.getValue().getBytes(StandardCharsets.UTF_8);
Optional<RuleSetEntity> ruleEntityOptional = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
if (ruleEntityOptional.isEmpty()) {
throw new NotFoundException(String.format("No rule file of type %s found for dossierTemplateId %s", ruleFileType, dossierTemplateId));
}
var data = ruleEntityOptional.get().getValue().getBytes(StandardCharsets.UTF_8);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.TEXT_PLAIN);

View File

@ -3,6 +3,7 @@ package com.iqser.red.service.persistence.v1.internal.api.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.exception.RulesTimeoutDetectedException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.RulesPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.internal.resources.RulesResource;
@ -22,20 +23,27 @@ public class RulesInternalController implements RulesResource {
public JSONPrimitive<String> getRules(@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId,
@PathVariable(RULE_FILE_TYPE_PARAMETER_NAME) RuleFileType ruleFileType) {
return new JSONPrimitive<>(rulesPersistenceService.getRules(dossierTemplateId, ruleFileType).getValue());
var rulesOptional = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
if (rulesOptional.isEmpty()) {
throw new NotFoundException(String.format("No rule file of type %s found for dossierTemplateId %s", ruleFileType, dossierTemplateId));
}
return new JSONPrimitive<>(rulesOptional.get().getValue());
}
@Override
public long getVersion(@PathVariable(DOSSIER_TEMPLATE_PARAMETER_NAME) String dossierTemplateId, @PathVariable(RULE_FILE_TYPE_PARAMETER_NAME) RuleFileType ruleFileType) {
var rules = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
var rulesOptional = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
if (rulesOptional.isEmpty()) {
throw new NotFoundException(String.format("No rule file of type %s found for dossierTemplateId %s", ruleFileType, dossierTemplateId));
}
if (rules.isTimeoutDetected()) {
if (rulesOptional.get().isTimeoutDetected()) {
throw new RulesTimeoutDetectedException(dossierTemplateId);
}
return rules.getVersion();
return rulesOptional.get().getVersion();
}

View File

@ -9,6 +9,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
@ -199,7 +200,11 @@ public class DossierTemplateExportService {
}
// add rule set
RuleSetEntity ruleSet = rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.ENTITY);
Optional<RuleSetEntity> ruleSetOptional = rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.ENTITY);
if (ruleSetOptional.isEmpty()) {
throw new NotFoundException(String.format("No rule file of type %s found for dossierTemplateId %s", RuleFileType.ENTITY, dossierTemplate.getId()));
}
RuleSetEntity ruleSet = ruleSetOptional.get();
fileSystemBackedArchiver.addEntries(new FileSystemBackedArchiver.ArchiveModel(folder,
getFilename(ExportFilename.RULES, RULE_EXT),
ruleSet.getValue().getBytes(StandardCharsets.UTF_8)));
@ -209,7 +214,11 @@ public class DossierTemplateExportService {
objectMapper.writeValueAsBytes(rulesExportModel)));
// add component rule set
try {
RuleSetEntity componentRuleSet = rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.COMPONENT);
Optional<RuleSetEntity> componentRuleSetOptional = rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.COMPONENT);
if (componentRuleSetOptional.isEmpty()) {
throw new NotFoundException(String.format("No rule file of type %s found for dossierTemplateId %s", RuleFileType.COMPONENT, dossierTemplate.getId()));
}
RuleSetEntity componentRuleSet = componentRuleSetOptional.get();
fileSystemBackedArchiver.addEntries(new FileSystemBackedArchiver.ArchiveModel(folder,
getFilename(ExportFilename.COMPONENT_RULES, RULE_EXT),
componentRuleSet.getValue().getBytes(StandardCharsets.UTF_8)));

View File

@ -168,11 +168,14 @@ public class DossierTemplateCloneService {
private void cloneRules(String dossierTemplateId, String clonedDossierTemplateId) {
for (RuleFileType ruleFileType : RuleFileType.values()) {
try {
rulesPersistenceService.setRules(rulesPersistenceService.getRules(dossierTemplateId, ruleFileType).getValue(), clonedDossierTemplateId, ruleFileType);
} catch (NotFoundException e) {
log.debug("No {} rules found, will not be cloned!", ruleFileType);
}
var rulesOptional = rulesPersistenceService.getRules(dossierTemplateId, ruleFileType);
if (rulesOptional.isEmpty()) {
log.debug("No {} rules found, will not be cloned!", ruleFileType);
} else {
rulesPersistenceService.setRules(rulesOptional.get().getValue(), clonedDossierTemplateId, ruleFileType);
}
}
}

View File

@ -140,15 +140,15 @@ public class DossierTemplatePersistenceService {
if (legalBasis == null || legalBasis.isEmpty()) {
return DossierTemplateStatus.INCOMPLETE;
}
try {
rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.ENTITY);
} catch (NotFoundException e) {
var rulesOptional = rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.ENTITY);
if (rulesOptional.isEmpty()) {
return DossierTemplateStatus.INCOMPLETE;
}
if (applicationType.equals("DocuMine")) {
try {
rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.COMPONENT);
} catch (NotFoundException e) {
var componentRulesOptional = rulesPersistenceService.getRules(dossierTemplate.getId(), RuleFileType.COMPONENT);
if (componentRulesOptional.isEmpty()) {
return DossierTemplateStatus.INCOMPLETE;
}
}

View File

@ -1,5 +1,7 @@
package com.iqser.red.service.persistence.management.v1.processor.service.persistence;
import java.util.Optional;
import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.RuleSetEntity;
@ -105,10 +107,9 @@ public class RulesPersistenceService {
@Transactional
public RuleSetEntity getRules(String dossierTemplateId, RuleFileType ruleFileType) {
public Optional<RuleSetEntity> getRules(String dossierTemplateId, RuleFileType ruleFileType) {
return ruleSetRepository.findByDossierTemplateIdAndRuleFileType(dossierTemplateId, ruleFileType.name())
.orElseThrow(() -> new NotFoundException(String.format("No rule file of type %s found for dossierTemplateId %s", ruleFileType, dossierTemplateId)));
return ruleSetRepository.findByDossierTemplateIdAndRuleFileType(dossierTemplateId, ruleFileType.name());
}

View File

@ -246,7 +246,7 @@ public class DossierTemplateCloneServiceTest {
OffsetDateTime validTo = OffsetDateTime.now().plusYears(4);
dummyTemplate.setValidTo(validTo);
when(rulesPersistenceService.getRules(anyString(), any())).thenReturn(new RuleSetEntity());
when(rulesPersistenceService.getRules(anyString(), any())).thenReturn(Optional.of(new RuleSetEntity()));
when(legalBasisMappingPersistenceService.getLegalBasisMapping(anyString())).thenReturn(List.of(LegalBasisEntity.builder()
.name("dummy-name")
.description("dummy-description")

View File

@ -1,6 +1,8 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -9,22 +11,32 @@ import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockMultipartFile;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.service.DossierTemplateManagementService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DossierTemplate;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.importexport.ImportDossierTemplateRequest;
import com.iqser.red.service.redaction.v1.model.DroolsBlacklistErrorMessage;
import com.iqser.red.service.redaction.v1.model.DroolsValidation;
import com.iqser.red.service.redaction.v1.model.RuleValidationModel;
import com.knecon.fforesight.tenantcommons.TenantContext;
import lombok.SneakyThrows;
@ -122,6 +134,31 @@ public class DossierTemplateImportTest extends AbstractPersistenceServerServiceT
assertThat(dt2.getName()).isEqualTo("Copy of EFSA sanitisation GFL v1");
}
@Test
void testDossierTemplateImportDMWithError() {
TenantContext.setTenantId("redaction");
List<DroolsBlacklistErrorMessage> blacklistErrorMessages = new ArrayList<>();
List<String> blacklistedKeywords = new ArrayList<>();
blacklistedKeywords.add("System.");
blacklistErrorMessages.add(DroolsBlacklistErrorMessage.builder().blacklistedKeywords(blacklistedKeywords).build());
when(redactionClient.testRules(new RuleValidationModel(RuleFileType.COMPONENT.name(), Mockito.any()))).thenReturn(DroolsValidation.builder()
.syntaxErrorMessages(Collections.emptyList())
.deprecatedWarnings(Collections.emptyList())
.blacklistErrorMessages(blacklistErrorMessages)
.build());
var archive = loadFileFromClasspath("Flora.zip");
var request = ImportDossierTemplateRequest.builder().archive(archive).updateExistingDossierTemplate(false).userId("system").build();
var e = assertThrows(BadRequestException.class,
() -> dossierTemplateManagementService.importDossierTemplate(request));
var reportTemplates = reportTemplateRepository.findAll();
assertThat(reportTemplates).hasSize(2);
var alldossierTemplates = dossierTemplateManagementService.getAllDossierTemplates();
assertThat(alldossierTemplates).hasSize(1);
}
@SneakyThrows
@ -145,6 +182,8 @@ public class DossierTemplateImportTest extends AbstractPersistenceServerServiceT
}
@SneakyThrows
@Test
public void testDossierTemplateImportOverwrite() {