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')
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