RED-7034 - Check for dossierDictionaryOnly flag when add to template dict is requested

- before adding / deleting entries to a dossier template dictionary check if the flag dossierDictionaryOnly is set true
- the same check is needed in case of manual redactions ; adding, removing
- add junit tests
This commit is contained in:
Corina Olariu 2023-07-07 09:54:09 +03:00
parent bbd705cdb1
commit 69566a2614
6 changed files with 162 additions and 41 deletions

View File

@ -25,6 +25,7 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.configur
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity;
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.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.EntryPersistenceService;
@ -379,4 +380,18 @@ public class DictionaryManagementService {
return currentVersion;
}
public void validateAddRemoveToDossierTemplateDictionary(String dossierTemplateTypeId) {
this.validateAddRemoveToDossierTemplateDictionary(dossierTemplateTypeId, true, true);
}
public void validateAddRemoveToDossierTemplateDictionary(String dossierTemplateTypeId, boolean isAddRemoveToDictionary, boolean isAddRemoveToAllDossiers) {
var type = dictionaryPersistenceService.getType(dossierTemplateTypeId);
if (isAddRemoveToDictionary && isAddRemoveToAllDossiers && type.isDossierDictionaryOnly()) {
throw new NotAllowedException("Adding / removing entry to dossier template dictionary is not allowed for this type: " + dossierTemplateTypeId);
}
}
}

View File

@ -67,13 +67,15 @@ public class DictionaryService {
@PreAuthorize("hasAuthority('" + ADD_DICTIONARY_ENTRY + "')")
public void addGlobalEntries(String type, String dossierTemplateId, List<String> entries, boolean removeCurrent, DictionaryEntryType dictionaryEntryType) {
addEntries(toTypeId(type, dossierTemplateId), entries, removeCurrent, dictionaryEntryType);
var typeId = toTypeId(type, dossierTemplateId);
dictionaryManagementService.validateAddRemoveToDossierTemplateDictionary(typeId);
addEntries(typeId, entries, removeCurrent, dictionaryEntryType);
}
public void addEntries(String type, List<String> entries, boolean removeCurrent, DictionaryEntryType dictionaryEntryType) {
public void addEntries(String typeId, List<String> entries, boolean removeCurrent, DictionaryEntryType dictionaryEntryType) {
dictionaryManagementService.addEntries(type, entries, removeCurrent, false, dictionaryEntryType);
dictionaryManagementService.addEntries(typeId, entries, removeCurrent, false, dictionaryEntryType);
}
@ -87,6 +89,8 @@ public class DictionaryService {
@PreAuthorize("hasAuthority('" + DELETE_DICTIONARY_ENTRY + "')")
public void deleteGlobalEntries(String type, String dossierTemplateId, List<String> entries, DictionaryEntryType dictionaryEntryType) {
var typeId = toTypeId(type, dossierTemplateId);
dictionaryManagementService.validateAddRemoveToDossierTemplateDictionary(typeId);
deleteEntries(toTypeId(type, dossierTemplateId), entries, dictionaryEntryType);
}
@ -419,4 +423,5 @@ public class DictionaryService {
return MagicConverter.convert(colorsService.getColors(dossierTemplateId), Colors.class);
}
}

View File

@ -15,7 +15,6 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
@ -100,6 +99,8 @@ public class ManualRedactionService {
dossierPersistenceService.getAndValidateDossier(dossierId);
var actionPerformed = false;
// validate add to dossier template dictionaries
addRedactionRequests.forEach(request -> dictionaryService.validateAddRemoveToDossierTemplateDictionary(request.getDossierTemplateTypeId(), request.isAddToDictionary(), request.isAddToAllDossiers()));
for (var addRedactionRequest : addRedactionRequests) {
if (addRedactionRequest.isAddToDictionary()) {
@ -279,13 +280,24 @@ public class ManualRedactionService {
public List<ManualAddResponse> addRemoveRedaction(String dossierId, String fileId, List<RemoveRedactionRequest> removeRedactionRequests) {
RedactionLog redactionLog = null;
var response = new ArrayList<ManualAddResponse>();
var dossier = dossierPersistenceService.getAndValidateDossier(dossierId);
RedactionLog redactionLog = fileManagementStorageService.getRedactionLog(dossier.getId(), fileId);
var actionPerformed = false;
var manualRedactions = manualRedactionProviderService.getManualRedactions(fileId);
//validate removing from dossier template dictionary
removeRedactionRequests.forEach(request -> {
if (request.isRemoveFromDictionary()) {
RedactionLogEntry redactionLogEntry = getRedactionLogEntry(redactionLog, request.getAnnotationId());
var dossierTemplateTypeId = toTypeId(redactionLogEntry.getType(), dossier.getDossierTemplateId());
dictionaryService.validateAddRemoveToDossierTemplateDictionary(dossierTemplateTypeId, request.isRemoveFromDictionary(), request.isRemoveFromAllDossiers());
}
});
for (var removeRedactionRequest : removeRedactionRequests) {
if (manualAddRedactionsContains(manualRedactions, removeRedactionRequest.getAnnotationId()) && AnnotationStatus.APPROVED.equals(removeRedactionRequest.getStatus())) {
@ -296,10 +308,6 @@ public class ManualRedactionService {
log.info("add removeRedaction for file {} and annotation {}", fileId, removeRedactionRequest.getAnnotationId());
var idRemoval = MagicConverter.convert(removeRedactionPersistenceService.insert(fileId, removeRedactionRequest), IdRemoval.class);
if (redactionLog == null) {
redactionLog = fileManagementStorageService.getRedactionLog(dossier.getId(), fileId);
}
Long commentId = null;
if (removeRedactionRequest.getComment() != null) {
commentId = addComment(fileId, removeRedactionRequest.getAnnotationId(), removeRedactionRequest.getComment(), removeRedactionRequest.getUser()).getId();
@ -367,16 +375,7 @@ public class ManualRedactionService {
if (removeFromDictionary) {
Optional<RedactionLogEntry> redactionLogEntryOptional = redactionLog.getRedactionLogEntry()
.stream()
.filter(entry -> entry.getId().equals(annotationId))
.findFirst();
if (redactionLogEntryOptional.isEmpty()) {
throw new NotFoundException("Annotation does not exist in redaction log.");
}
var redactionLogEntry = redactionLogEntryOptional.get();
RedactionLogEntry redactionLogEntry = getRedactionLogEntry(redactionLog, annotationId);
if (revert) {
var idRemovalEntity = removeRedactionPersistenceService.findRemoveRedaction(fileId, annotationId);
@ -413,6 +412,22 @@ public class ManualRedactionService {
}
private RedactionLogEntry getRedactionLogEntry(RedactionLog redactionLog, String annotationId) {
Optional<RedactionLogEntry> redactionLogEntryOptional = redactionLog.getRedactionLogEntry()
.stream()
.filter(entry -> entry.getId().equals(annotationId))
.findFirst();
if (redactionLogEntryOptional.isEmpty()) {
throw new NotFoundException("Annotation does not exist in redaction log.");
}
var redactionLogEntry = redactionLogEntryOptional.get();
return redactionLogEntry;
}
private String buildTypeId(RedactionLogEntry redactionLogEntry, DossierEntity dossier) {
if (redactionLogEntry.isDossierDictionaryEntry()) {

View File

@ -23,12 +23,17 @@ public class TypeProvider {
public TypeValue testAndProvideType(DossierTemplateModel dossierTemplate) {
return testAndProvideType(dossierTemplate, null, "test");
return testAndProvideType(dossierTemplate, null, "test", false);
}
public TypeValue testAndProvideType(DossierTemplateModel dossierTemplate, Dossier dossier, String typeName) {
return testAndProvideType(dossierTemplate, dossier, typeName, false);
}
public TypeValue testAndProvideType(DossierTemplateModel dossierTemplate, Dossier dossier, String typeName, boolean dossierDictionaryOnly) {
var type = new CreateTypeValue();
type.setType(typeName);
type.setDescription("test");
@ -42,7 +47,7 @@ public class TypeProvider {
type.setCaseInsensitive(true);
type.setDossierTemplateId(dossierTemplate.getId());
type.setHasDictionary(true);
type.setDossierDictionaryOnly(true);
type.setDossierDictionaryOnly(dossierDictionaryOnly);
dictionaryClient.addType(type);
var allTypes = dictionaryClient.getAllTypes(dossierTemplate.getDossierTemplateId(),dossier != null ? dossier.getId() : null,false);

View File

@ -2,8 +2,6 @@ package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@ -14,7 +12,6 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
@ -55,6 +52,33 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
TenantContext.setTenantId("redaction");
}
@Test
public void testAddEntriesToDossierTemplateDictionaryWithDossierDictioanryOnlyFlag() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", true);
assertThat(type.isDossierDictionaryOnly()).isTrue();
var entries = List.of("word1", "word2");
var falsePositives = List.of("false_positive1", "false_positive");
var falseRecommendations = List.of("false_recommendation1", "false_recommendation2");
Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY));
Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), falsePositives, false, null, DictionaryEntryType.FALSE_POSITIVE));
Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), falseRecommendations, false, null, DictionaryEntryType.FALSE_RECOMMENDATION));
var loadedType1 = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
assertThat(loadedType1).isNotNull();
assertThat(loadedType1.getEntries()).isNull();
assertThat(loadedType1.getFalsePositiveEntries()).isNull();
assertThat(loadedType1.getFalseRecommendationEntries()).isNull();
Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), entries, null, DictionaryEntryType.ENTRY));
Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), falsePositives, null, DictionaryEntryType.FALSE_POSITIVE));
Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), falseRecommendations, null, DictionaryEntryType.FALSE_RECOMMENDATION));
// Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntry(type.getType(), type.getDossierTemplateId(), entries.get(0), null, DictionaryEntryType.ENTRY));
// Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntry(type.getType(), type.getDossierTemplateId(), falsePositives.get(0), null, DictionaryEntryType.FALSE_POSITIVE));
// Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntry(type.getType(), type.getDossierTemplateId(), falseRecommendations.get(0), null, DictionaryEntryType.FALSE_RECOMMENDATION));
}
@Test
public void testAddFalsePositiveAndFalseRecommendation() {
@ -63,7 +87,7 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
var type = typeProvider.testAndProvideType(dossierTemplate);
assertThat(type.getRecommendationHexColor()).isEqualTo("#aaaaaa");
assertThat(type.getSkippedHexColor()).isEqualTo("#aaaaaa");
assertThat(type.isDossierDictionaryOnly()).isTrue();
assertThat(type.isDossierDictionaryOnly()).isFalse();
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("word1", "word2"), false, null, DictionaryEntryType.ENTRY);
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive"), false, null, DictionaryEntryType.FALSE_POSITIVE);
@ -200,7 +224,7 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
assertThat(dictionary.getEntries()).hasSize(1);
assertThat(dictionary.getEntries().iterator().next()).isEqualTo(word);
assertThat((dictionary.isDossierDictionaryOnly())).isTrue();
assertThat((dictionary.isDossierDictionaryOnly())).isFalse();
// Act & Assert: Delete word; Should have 'deleted' flag
entries = new ArrayList<>();
@ -394,7 +418,7 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
var type = typeProvider.testAndProvideType(dossierTemplate);
assertThat(type.getRecommendationHexColor()).isEqualTo("#aaaaaa");
assertThat(type.getSkippedHexColor()).isEqualTo("#aaaaaa");
assertThat(type.isDossierDictionaryOnly()).isTrue();
assertThat(type.isDossierDictionaryOnly()).isFalse();
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("word1", "word2", "word3"), false, null, DictionaryEntryType.ENTRY);
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive"), false, null, DictionaryEntryType.FALSE_POSITIVE);
@ -420,7 +444,7 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
false,
dossier.getDossierId(),
DictionaryEntryType.FALSE_RECOMMENDATION);
Exception exception = Assertions.assertThrows(FeignException.Unauthorized.class, () -> dictionaryClient.getMergedDictionaries(type.getType() + ";", dossierTemplate.getDossierTemplateId(), dossier.getDossierId()));
Assertions.assertThrows(FeignException.Unauthorized.class, () -> dictionaryClient.getMergedDictionaries(type.getType() + ";", dossierTemplate.getDossierTemplateId(), dossier.getDossierId()));
Dictionary mergedDict = dictionaryClient.getMergedDictionaries(type.getType(), dossierTemplate.getDossierTemplateId(), dossier.getDossierId());
assertThat(mergedDict).isNotNull();
@ -479,7 +503,7 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
var type = typeProvider.testAndProvideType(dossierTemplate);
assertThat(type.getRecommendationHexColor()).isEqualTo("#aaaaaa");
assertThat(type.getSkippedHexColor()).isEqualTo("#aaaaaa");
assertThat(type.isDossierDictionaryOnly()).isTrue();
assertThat(type.isDossierDictionaryOnly()).isFalse();
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("Charalampos", "Carina Wilson", "carlsen"), false, null, DictionaryEntryType.ENTRY);
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive"), false, null, DictionaryEntryType.FALSE_POSITIVE);
@ -504,6 +528,9 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
assertThat(loadedType1.getFalseRecommendationEntries().get(0)).isEqualTo("afalse_recommendation2");
assertThat(loadedType1.getFalseRecommendationEntries().get(1)).isEqualTo("false_recommendation1");
}
@Test
public void testCreateAndDeleteLargeDictionary() {

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
@ -92,6 +93,71 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
private InternalDictionaryClient internalDictionaryClient;
@Test
public void testRemoveToDossierTemplateWithDossierDictionaryOnlyTrue(){
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
var file = fileTesterAndProvider.testAndProvideFile(dossier);
var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", true);
assertThat(type.isDossierDictionaryOnly()).isTrue();
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("Luke Skywalker"), false, dossier.getDossierId(), DictionaryEntryType.ENTRY);
var redactionLog = new RedactionLog(1,
1,
List.of(RedactionLogEntry.builder().id("AnnotationId").type(type.getType()).value("Luke Skywalker").isDictionaryEntry(true).build()),
null,
0,
0,
0,
0);
fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.REDACTION_LOG, redactionLog);
when(redactionLogMergeService.provideRedactionLog(Mockito.any())).thenReturn(redactionLog);
Assertions.assertThrows(FeignException.Forbidden.class, () ->
manualRedactionClient.removeRedactionBulk(dossier.getId(),
file.getId(),
Set.of(RemoveRedactionRequest.builder().annotationId("AnnotationId").removeFromDictionary(true).removeFromAllDossiers(true).build())));//.get(0);
var dossierTemplateDictionary = internalDictionaryClient.getDictionaryForType(toTypeId(type.getType(), dossierTemplate.getDossierTemplateId()), null);
assertThat(dossierTemplateDictionary.getEntries().size()).isZero();
}
@Test
public void testAddToDossierTemplateWithDossierDictionaryOnlyTrue(){
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
var file = fileTesterAndProvider.testAndProvideFile(dossier);
var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", true);
assertThat(type.isDossierDictionaryOnly()).isTrue();
Assertions.assertThrows(FeignException.Forbidden.class, () ->
manualRedactionClient.addRedactionBulk(dossier.getId(),
file.getId(),
Set.of(AddRedactionRequest.builder()
.positions(List.of(Rectangle.builder().topLeftY(1).topLeftX(1).height(1).width(1).build()))
.section("section test")
.addToDictionary(true)
.addToAllDossiers(true)
.type(type.getType())
.reason("1")
.value("Luke Skywalker")
.legalBasis("1")
.sourceId("SourceId")
.build())));
var dossierTemplateDictionary = internalDictionaryClient.getDictionaryForType(toTypeId(type.getType(), dossierTemplate.getDossierTemplateId()), null);
assertThat(dossierTemplateDictionary.getEntries().size()).isZero();
}
@Test
public void testAddToAllDossiersIfDeletedInOneDossier(){
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
@ -100,10 +166,6 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
var type = typeProvider.testAndProvideType(dossierTemplate);
//FIXME should be created on the fly.
// CreateTypeValue dossierDictionaryType = MagicConverter.convert(type, CreateTypeValue.class);
// dictionaryClient.addType(dossierDictionaryType, dossier.getDossierId());
dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), List.of("Luke Skywalker"), dossier.getDossierId(), DictionaryEntryType.ENTRY);
var dossierDictionary = internalDictionaryClient.getDictionaryForType(toTypeId(type.getType(), dossierTemplate.getDossierTemplateId(), dossier.getDossierId()), null);
@ -143,10 +205,6 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
var type = typeProvider.testAndProvideType(dossierTemplate);
//FIXME should be created on the fly.
// CreateTypeValue dossierDictionaryType = MagicConverter.convert(type, CreateTypeValue.class);
// dictionaryClient.addType(dossierDictionaryType, dossier.getDossierId());
manualRedactionClient.addRedactionBulk(dossier.getId(),
file.getId(),
Set.of(AddRedactionRequest.builder()
@ -182,10 +240,6 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
entries.add("Darth Vader");
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);
//FIXME should be created on the fly.
// CreateTypeValue dossierDictionaryType = MagicConverter.convert(type, CreateTypeValue.class);
// dictionaryClient.addType(dossierDictionaryType, dossier.getDossierId());
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("Luke Skywalker"), false, dossier.getDossierId(), DictionaryEntryType.ENTRY);
var dossierTemplateDictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);