RED-8702: Explore document databases to store entityLog

This commit is contained in:
Maverick Studer 2024-04-11 15:51:58 +02:00
parent f870759747
commit 57cb10ba1d
9 changed files with 72 additions and 58 deletions

View File

@ -55,7 +55,7 @@ public class EntityLogController implements EntityLogResource {
@PreAuthorize("hasAuthority('" + READ_REDACTION_LOG + "')") @PreAuthorize("hasAuthority('" + READ_REDACTION_LOG + "')")
public EntityLogResponse getEntityLogWithEntriesOnPages(@PathVariable(DOSSIER_ID) String dossierId, public EntityLogResponse getEntityLogWithEntriesOnPages(@PathVariable(DOSSIER_ID) String dossierId,
@PathVariable(FILE_ID) String fileId, @PathVariable(FILE_ID) String fileId,
@RequestParam(value = "pageNumbers") List<Integer> pageNumbers) { @RequestParam(value = "pageNumbers", defaultValue = "") List<Integer> pageNumbers) {
accessControlService.checkViewPermissionsToDossier(dossierId); accessControlService.checkViewPermissionsToDossier(dossierId);
accessControlService.validateFileResourceExistence(fileId); accessControlService.validateFileResourceExistence(fileId);

View File

@ -55,7 +55,7 @@ public interface EntityLogResource {
@GetMapping(value = ENTITY_LOG_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE + "/pages", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = ENTITY_LOG_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE + "/pages", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Gets the entity log for a fileId with all entities found on the given page numbers", description = "None") @Operation(summary = "Gets the entity log for a fileId with all entities found on the given page numbers", description = "None")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "The dossier / file / entity log is not found.")}) @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "The dossier / file / entity log is not found.")})
EntityLogResponse getEntityLogWithEntriesOnPages(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestParam(value = "pageNumbers") List<Integer> pageNumbers); EntityLogResponse getEntityLogWithEntriesOnPages(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestParam(value = "pageNumbers", defaultValue = "") List<Integer> pageNumbers);
@GetMapping(value = ENTITY_LOG_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE + ANALYSIS_NUMBER_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = ENTITY_LOG_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE + ANALYSIS_NUMBER_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)

View File

@ -36,8 +36,8 @@ dependencies {
exclude(group = "com.iqser.red.service", module = "persistence-service-shared-api-v1") exclude(group = "com.iqser.red.service", module = "persistence-service-shared-api-v1")
} }
api("com.knecon.fforesight:jobs-commons:0.10.0") api("com.knecon.fforesight:jobs-commons:0.10.0")
api("com.knecon.fforesight:database-tenant-commons:0.23.0") api("com.knecon.fforesight:database-tenant-commons:0.24.0")
api("com.knecon.fforesight:keycloak-commons:0.27.0") api("com.knecon.fforesight:keycloak-commons:0.28.0")
api("com.knecon.fforesight:tracing-commons:0.5.0") api("com.knecon.fforesight:tracing-commons:0.5.0")
api("com.knecon.fforesight:swagger-commons:0.7.0") api("com.knecon.fforesight:swagger-commons:0.7.0")
api("com.giffing.bucket4j.spring.boot.starter:bucket4j-spring-boot-starter:0.4.0") api("com.giffing.bucket4j.spring.boot.starter:bucket4j-spring-boot-starter:0.4.0")

View File

@ -47,7 +47,6 @@ import com.knecon.fforesight.databasetenantcommons.DatabaseTenantCommonsAutoConf
import com.knecon.fforesight.jobscommons.JobsAutoConfiguration; import com.knecon.fforesight.jobscommons.JobsAutoConfiguration;
import com.knecon.fforesight.keycloakcommons.DefaultKeyCloakCommonsAutoConfiguration; import com.knecon.fforesight.keycloakcommons.DefaultKeyCloakCommonsAutoConfiguration;
import com.knecon.fforesight.mongo.database.commons.MongoDatabaseCommonsAutoConfiguration; import com.knecon.fforesight.mongo.database.commons.MongoDatabaseCommonsAutoConfiguration;
import com.knecon.fforesight.mongo.database.commons.liquibase.EnableMongoLiquibase;
import com.knecon.fforesight.swaggercommons.SpringDocAutoConfiguration; import com.knecon.fforesight.swaggercommons.SpringDocAutoConfiguration;
import com.knecon.fforesight.tenantcommons.MultiTenancyAutoConfiguration; import com.knecon.fforesight.tenantcommons.MultiTenancyAutoConfiguration;
import com.knecon.fforesight.tenantcommons.MultiTenancyMessagingConfiguration; import com.knecon.fforesight.tenantcommons.MultiTenancyMessagingConfiguration;
@ -68,7 +67,6 @@ import lombok.extern.slf4j.Slf4j;
@EnableCaching @EnableCaching
@EnableConfigurationProperties({FileManagementServiceSettings.class}) @EnableConfigurationProperties({FileManagementServiceSettings.class})
@EnableMongoRepositories(basePackages = "com.iqser.red.service.persistence") @EnableMongoRepositories(basePackages = "com.iqser.red.service.persistence")
@EnableMongoLiquibase
@ImportAutoConfiguration({StorageAutoConfiguration.class, JobsAutoConfiguration.class, DatabaseTenantCommonsAutoConfiguration.class, MultiTenancyAutoConfiguration.class, SpringDocAutoConfiguration.class, DefaultKeyCloakCommonsAutoConfiguration.class, MongoDatabaseCommonsAutoConfiguration.class}) @ImportAutoConfiguration({StorageAutoConfiguration.class, JobsAutoConfiguration.class, DatabaseTenantCommonsAutoConfiguration.class, MultiTenancyAutoConfiguration.class, SpringDocAutoConfiguration.class, DefaultKeyCloakCommonsAutoConfiguration.class, MongoDatabaseCommonsAutoConfiguration.class})
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, CassandraAutoConfiguration.class, DataSourceAutoConfiguration.class, LiquibaseAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) @SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, CassandraAutoConfiguration.class, DataSourceAutoConfiguration.class, LiquibaseAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@Import({PersistenceServiceExternalApiConfigurationV2.class, PersistenceServiceExternalApiConfiguration.class, PersistenceServiceInternalApiConfiguration.class, PersistenceServiceExternalApiCacheConfiguration.class, MultiTenancyWebConfiguration.class, PersistenceServiceProcessorConfiguration.class, MessagingConfiguration.class, MultiTenancyMessagingConfiguration.class}) @Import({PersistenceServiceExternalApiConfigurationV2.class, PersistenceServiceExternalApiConfiguration.class, PersistenceServiceInternalApiConfiguration.class, PersistenceServiceExternalApiCacheConfiguration.class, MultiTenancyWebConfiguration.class, PersistenceServiceProcessorConfiguration.class, MessagingConfiguration.class, MultiTenancyMessagingConfiguration.class})

View File

@ -108,6 +108,8 @@ import com.iqser.red.storage.commons.utils.FileSystemBackedStorageService;
import com.knecon.fforesight.databasetenantcommons.providers.TenantCreatedListener; import com.knecon.fforesight.databasetenantcommons.providers.TenantCreatedListener;
import com.knecon.fforesight.databasetenantcommons.providers.events.TenantCreatedEvent; import com.knecon.fforesight.databasetenantcommons.providers.events.TenantCreatedEvent;
import com.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter; import com.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter;
import com.knecon.fforesight.mongo.database.commons.liquibase.MongoTenantCreatedEvent;
import com.knecon.fforesight.mongo.database.commons.liquibase.MongoTenantCreatedListener;
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService; import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
import com.knecon.fforesight.tenantcommons.TenantContext; import com.knecon.fforesight.tenantcommons.TenantContext;
import com.knecon.fforesight.tenantcommons.TenantsClient; import com.knecon.fforesight.tenantcommons.TenantsClient;
@ -237,6 +239,10 @@ public abstract class AbstractPersistenceServerServiceTest {
protected EncryptionDecryptionService encryptionDecryptionService; protected EncryptionDecryptionService encryptionDecryptionService;
@Autowired @Autowired
protected TenantCreatedListener tenantCreatedListener; protected TenantCreatedListener tenantCreatedListener;
@Autowired
protected MongoTenantCreatedListener mongoTenantCreatedListener;
@Autowired
protected MongoTestConfig mongoTestConfig;
@MockBean @MockBean
protected ReportTemplatePlaceholderClient reportTemplatePlaceholderClient; protected ReportTemplatePlaceholderClient reportTemplatePlaceholderClient;
@ -364,55 +370,55 @@ public abstract class AbstractPersistenceServerServiceTest {
.build()); .build());
redactionTenant.setMongoDBConnection(MongoDBConnection.builder() redactionTenant.setMongoDBConnection(MongoDBConnection.builder()
.host(mongoDbContainer.getHost()) .prefix("mongodb")
.port(String.valueOf(mongoDbContainer.getFirstMappedPort()))
.username(MONGO_USERNAME) .username(MONGO_USERNAME)
.password(encryptionDecryptionService.encrypt(MONGO_PASSWORD)) .password(encryptionDecryptionService.encrypt(MONGO_PASSWORD))
.address(mongoDbContainer.getHost() + ":" + mongoDbContainer.getFirstMappedPort())
.database(MONGO_DATABASE) .database(MONGO_DATABASE)
.options("")
.build()); .build());
var redactionTenant2 = new TenantResponse();
redactionTenant2.setTenantId("redaction2");
redactionTenant2.setGuid("redaction2");
redactionTenant2.setDisplayName("redaction2");
redactionTenant2.setAuthDetails(new AuthDetails());
redactionTenant2.setDatabaseConnection(DatabaseConnection.builder()
.driver("postgresql")
.host(postgreSQLContainerMaster.getHost())
.port(port)
.database("integration-tests-db-master")
.schema("public")
.username("sa")
.password(encryptionDecryptionService.encrypt("sa"))
.build());
var redactionTenant2 = new TenantResponse(); redactionTenant2.setSearchConnection(SearchConnection.builder()
redactionTenant2.setTenantId("redaction2"); .hosts(Set.of("elasticsearchHost"))
redactionTenant2.setGuid("redaction2"); .port(9200)
redactionTenant2.setDisplayName("redaction2"); .scheme("https")
redactionTenant2.setAuthDetails(new AuthDetails()); .username("elastic")
redactionTenant2.setDatabaseConnection(DatabaseConnection.builder() .numberOfShards("1")
.driver("postgresql") .numberOfReplicas("5")
.host(postgreSQLContainerMaster.getHost()) .build());
.port(port)
.database("integration-tests-db-master")
.schema("public")
.username("sa")
.password(encryptionDecryptionService.encrypt("sa"))
.build());
redactionTenant2.setSearchConnection(SearchConnection.builder() redactionTenant2.setS3StorageConnection(S3StorageConnection.builder()
.hosts(Set.of("elasticsearchHost")) .key("key")
.port(9200) .secret("secret")
.scheme("https") .signerType("signerType")
.username("elastic") .bucketName("bucketName")
.numberOfShards("1") .region("eu")
.numberOfReplicas("5") .endpoint("endpoint")
.build()); .build());
redactionTenant2.setS3StorageConnection(S3StorageConnection.builder() redactionTenant2.setMongoDBConnection(MongoDBConnection.builder()
.key("key") .prefix("mongodb")
.secret("secret") .username(MONGO_USERNAME)
.signerType("signerType") .password(encryptionDecryptionService.encrypt(MONGO_PASSWORD))
.bucketName("bucketName") .address(mongoDbContainer.getHost() + ":" + mongoDbContainer.getFirstMappedPort())
.region("eu") .database("redaction2")
.endpoint("endpoint") .options("")
.build()); .build());
redactionTenant2.setMongoDBConnection(MongoDBConnection.builder()
.host(mongoDbContainer.getHost())
.port(String.valueOf(mongoDbContainer.getFirstMappedPort()))
.username(MONGO_USERNAME)
.password(encryptionDecryptionService.encrypt(MONGO_PASSWORD))
.database("redaction2")
.build());
when(tenantsClient.getTenant("redaction")).thenReturn(redactionTenant); when(tenantsClient.getTenant("redaction")).thenReturn(redactionTenant);
when(tenantsClient.getTenant("redaction2")).thenReturn(redactionTenant2); when(tenantsClient.getTenant("redaction2")).thenReturn(redactionTenant2);
@ -421,6 +427,8 @@ public abstract class AbstractPersistenceServerServiceTest {
try { try {
tenantCreatedListener.createTenant(new TenantCreatedEvent("redaction")); tenantCreatedListener.createTenant(new TenantCreatedEvent("redaction"));
tenantCreatedListener.createTenant(new TenantCreatedEvent("redaction2")); tenantCreatedListener.createTenant(new TenantCreatedEvent("redaction2"));
mongoTenantCreatedListener.createTenant(new MongoTenantCreatedEvent("redaction"));
mongoTenantCreatedListener.createTenant(new MongoTenantCreatedEvent("redaction2"));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -0,0 +1,11 @@
package com.iqser.red.service.peristence.v1.server.integration.utils;
import org.springframework.context.annotation.Configuration;
import com.knecon.fforesight.mongo.database.commons.liquibase.EnableMongoLiquibase;
@Configuration
@EnableMongoLiquibase
public class MongoTestConfig {
}

View File

@ -9,7 +9,7 @@ dependencies {
api(project(":persistence-service-shared-api-v1")) api(project(":persistence-service-shared-api-v1"))
api("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.16.0") api("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.16.0")
api("com.google.guava:guava:31.1-jre") api("com.google.guava:guava:31.1-jre")
api("com.knecon.fforesight:mongo-database-commons:0.7.0") api("com.knecon.fforesight:mongo-database-commons:0.9.0")
api("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootStarterVersion}") api("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootStarterVersion}")
api("org.springframework.boot:spring-boot-starter-validation:3.1.3") api("org.springframework.boot:spring-boot-starter-validation:3.1.3")
testImplementation("com.iqser.red.commons:test-commons:2.1.0") testImplementation("com.iqser.red.commons:test-commons:2.1.0")

View File

@ -16,10 +16,6 @@ public interface EntityLogEntryDocumentRepository extends MongoRepository<Entity
List<EntityLogEntryDocument> findByEntityLogIdAndManualChangesNotEmpty(String entityLogId); List<EntityLogEntryDocument> findByEntityLogIdAndManualChangesNotEmpty(String entityLogId);
@Query("{ 'entityLogId' : ?0, 'changes.analysisNumber' : ?1 }")
List<EntityLogEntryDocument> findByEntityLogIdAndChangesAnalysisNumber(String entityLogId, int analysisNumber);
@Query("{ 'entityLogId' : ?0, 'changes.analysisNumber' : ?1 }") @Query("{ 'entityLogId' : ?0, 'changes.analysisNumber' : ?1 }")
List<EntityLogEntryDocument> findByEntityLogIdAndChangesAnalysisNumberEquals(String entityLogId, Integer analysisNumber); List<EntityLogEntryDocument> findByEntityLogIdAndChangesAnalysisNumberEquals(String entityLogId, Integer analysisNumber);

View File

@ -175,13 +175,6 @@ public class EntityLogMongoService {
} }
public List<EntityLogEntry> findEntityLogEntriesByAnalysisNumber(String dossierId, String fileId, int analysisNumber) {
return entityLogEntryDocumentRepository.findByEntityLogIdAndChangesAnalysisNumber(mapper.getLogId(dossierId, fileId), analysisNumber)
.stream()
.map(mapper::fromLogEntryDocument)
.toList();
}
public Set<Integer> findFirstContainingNodeIdForEachEntry(String dossierId, String fileId, Collection<String> entryIds) { public Set<Integer> findFirstContainingNodeIdForEachEntry(String dossierId, String fileId, Collection<String> entryIds) {
@ -268,6 +261,14 @@ public class EntityLogMongoService {
return optionalEntityLog; return optionalEntityLog;
} }
public List<EntityLogEntry> findEntityLogEntriesByAnalysisNumber(String dossierId, String fileId, int analysisNumber) {
return entityLogEntryDocumentRepository.findByEntityLogIdAndChangesAnalysisNumberEquals(mapper.getLogId(dossierId, fileId), analysisNumber)
.stream()
.map(mapper::fromLogEntryDocument)
.toList();
}
public Optional<EntityLog> findEntityLogWithEntriesByAnalysisNumber(String dossierId, String fileId, Integer analysisNumber) { public Optional<EntityLog> findEntityLogWithEntriesByAnalysisNumber(String dossierId, String fileId, Integer analysisNumber) {
String entityLogId = mapper.getLogId(dossierId, fileId); String entityLogId = mapper.getLogId(dossierId, fileId);