diff options
| author | Paul-Christian Volkmer | 2026-01-21 14:10:32 +0100 |
|---|---|---|
| committer | GitHub | 2026-01-21 13:10:32 +0000 |
| commit | 623eb1b250e03772f0311ea088de2a9a5885df2e (patch) | |
| tree | 294ef9b7108c1a1f3ddedfa2a407e8c9e317764c | |
| parent | dd7ad122b0ef97b13cf63c53fcb46403dcb80c5b (diff) | |
feat: always send dataset without consent (#243)
This changes the behavior of the application!
Any dataset will be forwarded to DNPM:DIP, even w/o
valid consent information.
DNPM:DIP will return issues if MV consent or broad
consent is missing.
| -rw-r--r-- | src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt | 43 | ||||
| -rw-r--r-- | src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt | 43 |
2 files changed, 56 insertions, 30 deletions
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt index 2b80167..8713f06 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt @@ -1,7 +1,8 @@ /* * This file is part of ETL-Processor * - * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors + * Copyright (c) 2023 Comprehensive Cancer Center Mainfranken + * Copyright (c) 2023-2026 Datenintegrationszentrum Philipps-Universität Marburg and Contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published @@ -23,11 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import dev.dnpm.etl.processor.* import dev.dnpm.etl.processor.config.AppConfigProperties import dev.dnpm.etl.processor.consent.TtpConsentStatus -import dev.dnpm.etl.processor.monitoring.Report -import dev.dnpm.etl.processor.monitoring.Request -import dev.dnpm.etl.processor.monitoring.RequestStatus -import dev.dnpm.etl.processor.monitoring.RequestType -import dev.dnpm.etl.processor.monitoring.SubmissionType +import dev.dnpm.etl.processor.monitoring.* import dev.dnpm.etl.processor.output.DeleteRequest import dev.dnpm.etl.processor.output.DnpmV2MtbFileRequest import dev.dnpm.etl.processor.output.MtbFileRequest @@ -36,18 +33,16 @@ import dev.dnpm.etl.processor.pseudonym.PseudonymizeService import dev.dnpm.etl.processor.pseudonym.addGenomDeTan import dev.dnpm.etl.processor.pseudonym.anonymizeContentWith import dev.dnpm.etl.processor.pseudonym.pseudonymizeWith -import dev.pcvolkmer.mv64e.mtb.ConsentProvision -import dev.pcvolkmer.mv64e.mtb.ModelProjectConsentPurpose import dev.pcvolkmer.mv64e.mtb.Mtb import dev.pcvolkmer.mv64e.mtb.MvhSubmissionType -import java.time.Instant -import java.util.* import org.apache.commons.codec.binary.Base32 import org.apache.commons.codec.digest.DigestUtils import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Service +import java.time.Instant +import java.util.* @Service class RequestProcessor( @@ -71,28 +66,16 @@ class RequestProcessor( val isConsentOk = consentProcessor != null && consentProcessor.consentGatedCheckAndTryEmbedding(mtbFile) || consentProcessor == null - if (isConsentOk) { - if (isGenomDeConsented(mtbFile)) { - mtbFile addGenomDeTan pseudonymizeService - } - mtbFile pseudonymizeWith pseudonymizeService - mtbFile anonymizeContentWith pseudonymizeService - val request = DnpmV2MtbFileRequest(requestId, transformationService.transform(mtbFile)) - saveAndSend(request) - } else { - logger.warn("consent check failed file will not be processed further!") - applicationEventPublisher.publishEvent( - ResponseEvent(requestId, Instant.now(), RequestStatus.NO_CONSENT) - ) + + if (!isConsentOk) { + logger.warn("consent check failed but will be sent to DNPM:DIP!") } - } - private fun isGenomDeConsented(mtbFile: Mtb): Boolean { - val isModelProjectConsented = - mtbFile.metadata?.modelProjectConsent?.provisions?.any { p -> - p.purpose == ModelProjectConsentPurpose.SEQUENCING && p.type == ConsentProvision.PERMIT - } == true - return isModelProjectConsented + mtbFile addGenomDeTan pseudonymizeService + mtbFile pseudonymizeWith pseudonymizeService + mtbFile anonymizeContentWith pseudonymizeService + val request = DnpmV2MtbFileRequest(requestId, transformationService.transform(mtbFile)) + saveAndSend(request) } private fun <T> saveAndSend(request: MtbFileRequest<T>) { diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt index 851c1a1..edd9ffe 100644 --- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt +++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt @@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import dev.dnpm.etl.processor.Fingerprint import dev.dnpm.etl.processor.PatientId import dev.dnpm.etl.processor.PatientPseudonym +import dev.dnpm.etl.processor.RequestId import dev.dnpm.etl.processor.config.AppConfigProperties import dev.dnpm.etl.processor.consent.TtpConsentStatus import dev.dnpm.etl.processor.monitoring.Request @@ -478,6 +479,48 @@ class RequestProcessorTest { assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS) } + @Test + fun testShouldSendRequestWithoutConsent() { + doAnswer { "PSEUDONYM" }.whenever(pseudonymizeService).patientPseudonym(anyValueClass()) + + doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) } + .whenever(sender) + .send(any<DnpmV2MtbFileRequest>()) + + doAnswer { it.arguments.first() } + .whenever(transformationService) + .transform(any<Mtb>()) + + val mtbFile = + Mtb.builder() + .patient(Patient.builder().id("123").build()) + .metadata(MvhMetadata()) + .episodesOfCare( + listOf( + MtbEpisodeOfCare.builder() + .id("1") + .patient(Reference.builder().id("123").build()) + .period( + PeriodDate.builder() + .start(Date.from(Instant.parse("2021-01-01T00:00:00.00Z"))) + .build() + ) + .build() + ) + ) + .build() + + this.requestProcessor.processMtbFile( + mtbFile, + randomRequestId(), + ) + + val eventCaptor = argumentCaptor<ResponseEvent>() + verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture()) + assertThat(eventCaptor.firstValue).isNotNull + assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS) + } + @Test fun testShouldSendDeleteRequestAndSendErrorEvent() { doAnswer { "PSEUDONYM" }.whenever(pseudonymizeService).patientPseudonym(anyValueClass()) |
