From dfc9de78ceb8753392aac16e99dfc25346634ac9 Mon Sep 17 00:00:00 2001 From: jlidke Date: Wed, 23 Jul 2025 22:11:47 +0200 Subject: 119 add transaction (#124) --- .../dnpm/etl/processor/config/AppConfigProperties.kt | 3 ++- .../etl/processor/pseudonym/AnonymizingGenerator.kt | 15 ++++++++++++++- .../dnpm/etl/processor/pseudonym/PseudonymizeService.kt | 4 ++++ .../dev/dnpm/etl/processor/pseudonym/extensions.kt | 5 +++++ .../dev/dnpm/etl/processor/services/ConsentProcessor.kt | 2 +- .../dev/dnpm/etl/processor/services/RequestProcessor.kt | 17 +++++++++++++++-- 6 files changed, 41 insertions(+), 5 deletions(-) (limited to 'src/main/kotlin/dev/dnpm') diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt index a2ea032..207785e 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt @@ -48,7 +48,8 @@ data class PseudonymizeConfigProperties( @ConfigurationProperties(GPasConfigProperties.NAME) data class GPasConfigProperties( val uri: String?, - val target: String = "etl-processor", + val patientDomain: String = "etl-processor", + val genomDeTanDomain: String = "ccdn", val username: String?, val password: String?, ) { diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt index c03db12..0537cbb 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/AnonymizingGenerator.kt @@ -21,9 +21,12 @@ package dev.dnpm.etl.processor.pseudonym import org.apache.commons.codec.binary.Base32 import org.apache.commons.codec.digest.DigestUtils - +import java.security.SecureRandom class AnonymizingGenerator : Generator { + companion object fun getSecureRandom() : SecureRandom { + return SecureRandom() + } override fun generate(id: String): String { return Base32().encodeAsString(DigestUtils.sha256(id)) @@ -31,4 +34,14 @@ class AnonymizingGenerator : Generator { .lowercase() } + @OptIn(ExperimentalStdlibApi::class) + override fun generateGenomDeTan(id: String?): String { + + val bytes = ByteArray(64 / 2) + getSecureRandom().nextBytes(bytes) + + return bytes.joinToString("") { "%02x".format(it) } + + } + } \ No newline at end of file diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt index e80f6ec..96225a9 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/PseudonymizeService.kt @@ -35,6 +35,10 @@ class PseudonymizeService( } } + fun genomDeTan(patientId: PatientId): String { + return generator.generateGenomDeTan(patientId.value) + } + fun prefix(): String { return configProperties.prefix } diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt index 77f3399..50d5b20 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt @@ -349,3 +349,8 @@ fun Mtb.ensureMetaDataIsInitialized() { this.metadata.modelProjectConsent.provisions.toMutableList() } } + +infix fun Mtb.addGenomDeTan(pseudonymizeService: PseudonymizeService) +{ + this.metadata.transferTan = pseudonymizeService.genomDeTan(PatientId(this.patient.id)) +} \ No newline at end of file diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt index 3841641..11aff57 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt @@ -38,7 +38,7 @@ class ConsentProcessor( /** * In case an instance of {@link ICheckConsent} is active, consent will be embedded and checked. * - * Logik: + * Logic: * * true IF consent check is disabled. * * true IF broad consent (BC) has been given. * * true BC has been asked AND declined but genomDe consent has been consented. 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 bb226c0..f2e8390 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt @@ -30,8 +30,11 @@ import dev.dnpm.etl.processor.monitoring.RequestStatus import dev.dnpm.etl.processor.monitoring.RequestType import dev.dnpm.etl.processor.output.* 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 org.apache.commons.codec.binary.Base32 import org.apache.commons.codec.digest.DigestUtils @@ -76,9 +79,12 @@ class RequestProcessor( fun processMtbFile(mtbFile: Mtb, requestId: RequestId) { val pid = PatientId(extractPatientIdentifier(mtbFile)) - val isConsentOk = consentProcessor != null && - consentProcessor.consentGatedCheckAndTryEmbedding(mtbFile) || consentProcessor == null + 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)) @@ -93,6 +99,13 @@ class RequestProcessor( } } + 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 + } + private fun saveAndSend(request: MtbFileRequest, pid: PatientId) { requestService.save( Request( -- cgit v1.2.3