summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt1
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt3
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt1
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt6
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt5
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt4
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/types.kt8
-rw-r--r--src/main/resources/db/migration/mariadb/V0_15_0_1__Tan.sql2
-rw-r--r--src/main/resources/db/migration/postgresql/V0_15_0_1__Tan.sql2
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt81
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt10
-rw-r--r--src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt1
12 files changed, 123 insertions, 1 deletions
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt
index 98fee3f..17b49eb 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/monitoring/RequestRepositoryTest.kt
@@ -63,6 +63,7 @@ class RequestRepositoryTest : AbstractTestcontainerTest() {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant.parse("2023-07-07T00:00:00Z"),
)
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt
index 0b30e94..63dd5dc 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/services/RequestServiceIntegrationTest.kt
@@ -78,6 +78,7 @@ class RequestServiceIntegrationTest : AbstractTestcontainerTest() {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-07-07T02:00:00Z"),
),
// Should be ignored - wrong patient ID -->
@@ -89,6 +90,7 @@ class RequestServiceIntegrationTest : AbstractTestcontainerTest() {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant.parse("2023-08-08T00:00:00Z"),
),
// <--
@@ -100,6 +102,7 @@ class RequestServiceIntegrationTest : AbstractTestcontainerTest() {
RequestType.DELETE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-08-08T02:00:00Z"),
),
)
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt
index 9e85d08..c2b6759 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/HomeControllerTest.kt
@@ -159,6 +159,7 @@ class HomeControllerTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.now(),
Report("Test"),
)
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt
index 926f315..2568b1b 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/web/StatisticsRestControllerTest.kt
@@ -22,6 +22,7 @@ package dev.dnpm.etl.processor.web
import dev.dnpm.etl.processor.Fingerprint
import dev.dnpm.etl.processor.PatientId
import dev.dnpm.etl.processor.PatientPseudonym
+import dev.dnpm.etl.processor.Tan
import dev.dnpm.etl.processor.config.AppConfiguration
import dev.dnpm.etl.processor.config.AppSecurityConfiguration
import dev.dnpm.etl.processor.monitoring.CountedState
@@ -188,6 +189,7 @@ class StatisticsRestControllerTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant
.now()
.atZone(zoneId)
@@ -204,6 +206,7 @@ class StatisticsRestControllerTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant
.now()
.atZone(zoneId)
@@ -220,6 +223,7 @@ class StatisticsRestControllerTest {
RequestType.DELETE,
SubmissionType.TEST,
RequestStatus.ERROR,
+ Tan.empty(),
Instant
.now()
.atZone(zoneId)
@@ -236,6 +240,7 @@ class StatisticsRestControllerTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.DUPLICATION,
+ Tan.empty(),
Instant
.now()
.atZone(zoneId)
@@ -252,6 +257,7 @@ class StatisticsRestControllerTest {
RequestType.DELETE,
SubmissionType.TEST,
RequestStatus.UNKNOWN,
+ Tan.empty(),
Instant
.now()
.atZone(zoneId)
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt
index b1cc1ed..9aede20 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/monitoring/Request.kt
@@ -43,6 +43,7 @@ data class Request(
val type: RequestType,
@Column("submission_type") val submissionType: SubmissionType,
var status: RequestStatus,
+ @Column("tan") val tan: Tan = Tan.empty(),
var processedAt: Instant = Instant.now(),
@Embedded.Nullable var report: Report? = null,
@Column("submission_accepted") var submissionAccepted: Boolean = false,
@@ -55,6 +56,7 @@ data class Request(
type: RequestType,
submissionType: SubmissionType,
status: RequestStatus,
+ tan: Tan,
) : this(
null,
uuid,
@@ -64,6 +66,7 @@ data class Request(
type,
submissionType,
status,
+ tan,
Instant.now(),
)
@@ -75,6 +78,7 @@ data class Request(
type: RequestType,
submissionType: SubmissionType,
status: RequestStatus,
+ tan: Tan,
processedAt: Instant,
) : this(
null,
@@ -85,6 +89,7 @@ data class Request(
type,
submissionType,
status,
+ tan,
processedAt,
)
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 b14d6f4..fe1fd3b 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt
@@ -107,6 +107,7 @@ class RequestProcessor(
RequestType.MTB_FILE,
submissionType,
RequestStatus.BLOCKED_INITIAL,
+ Tan(request.content.metadata?.transferTan.orEmpty())
)
)
// Exit - no further processing
@@ -135,6 +136,7 @@ class RequestProcessor(
RequestType.MTB_FILE,
submissionType,
RequestStatus.UNKNOWN,
+ Tan(request.content.metadata?.transferTan.orEmpty()),
)
)
@@ -228,6 +230,7 @@ class RequestProcessor(
RequestType.DELETE,
SubmissionType.UNKNOWN,
requestStatus,
+ Tan.empty()
)
)
@@ -256,6 +259,7 @@ class RequestProcessor(
type = RequestType.DELETE,
submissionType = SubmissionType.UNKNOWN,
report = Report("Fehler bei der Pseudonymisierung"),
+ tan = Tan.empty(),
)
)
}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/types.kt b/src/main/kotlin/dev/dnpm/etl/processor/types.kt
index 87f5fb2..9244297 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/types.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/types.kt
@@ -48,6 +48,14 @@ fun emptyPatientId() = PatientId("")
fun emptyPatientPseudonym() = PatientPseudonym("")
+@JvmInline value class Tan(val value: String) {
+ fun isValid() = value.matches(Regex("^[a-fA-F0-9]{64}$"))
+
+ companion object {
+ fun empty() = Tan("")
+ }
+}
+
/**
* Custom MediaTypes
*
diff --git a/src/main/resources/db/migration/mariadb/V0_15_0_1__Tan.sql b/src/main/resources/db/migration/mariadb/V0_15_0_1__Tan.sql
new file mode 100644
index 0000000..2076163
--- /dev/null
+++ b/src/main/resources/db/migration/mariadb/V0_15_0_1__Tan.sql
@@ -0,0 +1,2 @@
+ALTER TABLE request ADD COLUMN tan varchar(64) not null default '';
+UPDATE request SET tan = '';
diff --git a/src/main/resources/db/migration/postgresql/V0_15_0_1__Tan.sql b/src/main/resources/db/migration/postgresql/V0_15_0_1__Tan.sql
new file mode 100644
index 0000000..2076163
--- /dev/null
+++ b/src/main/resources/db/migration/postgresql/V0_15_0_1__Tan.sql
@@ -0,0 +1,2 @@
+ALTER TABLE request ADD COLUMN tan varchar(64) not null default '';
+UPDATE request SET tan = '';
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 edd9ffe..afa6872 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestProcessorTest.kt
@@ -23,7 +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.Tan
import dev.dnpm.etl.processor.config.AppConfigProperties
import dev.dnpm.etl.processor.consent.TtpConsentStatus
import dev.dnpm.etl.processor.monitoring.Request
@@ -109,6 +109,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-08-08T02:00:00Z"),
)
}
@@ -165,6 +166,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-08-08T02:00:00Z"),
)
}
@@ -221,6 +223,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-08-08T02:00:00Z"),
)
}
@@ -281,6 +284,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-08-08T02:00:00Z"),
)
}
@@ -299,6 +303,10 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
+ doAnswer { "f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2" }
+ .whenever(pseudonymizeService)
+ .genomDeTan(anyValueClass())
+
doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
@@ -360,6 +368,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.INITIAL,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2026-01-05T09:00:00Z"),
submissionAccepted = true,
),
@@ -372,6 +381,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.INITIAL,
RequestStatus.BLOCKED_INITIAL,
+ Tan.empty(),
Instant.parse("2026-01-05T10:00:00Z"),
submissionAccepted = false,
),
@@ -393,6 +403,10 @@ class RequestProcessorTest {
.whenever(pseudonymizeService)
.patientPseudonym(anyValueClass())
+ doAnswer { "f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2" }
+ .whenever(pseudonymizeService)
+ .genomDeTan(anyValueClass())
+
doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
@@ -434,6 +448,7 @@ class RequestProcessorTest {
verify(sender, times(1)).send(requestCaptor.capture())
assertThat(requestCaptor.firstValue).isNotNull
assertThat(requestCaptor.firstValue.content.metadata.type).isEqualTo(MvhSubmissionType.ADDITION)
+ assertThat(requestCaptor.firstValue.content.metadata.transferTan).isEqualTo("f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2")
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@@ -597,6 +612,68 @@ class RequestProcessorTest {
assertThat(eventCaptor.firstValue.status).isEqualTo(RequestStatus.SUCCESS)
}
+ @Test
+ fun testShouldSaveRequestWithGenomDeTan() {
+
+ doAnswer { false }
+ .whenever(requestService)
+ .isLastRequestWithKnownStatusDeletion(anyValueClass())
+
+ doAnswer { MtbFileSender.Response(status = RequestStatus.SUCCESS) }
+ .whenever(sender)
+ .send(any<DnpmV2MtbFileRequest>())
+
+ doAnswer { it.arguments[0] as String }
+ .whenever(pseudonymizeService)
+ .patientPseudonym(anyValueClass())
+
+ doAnswer { "f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2" }
+ .whenever(pseudonymizeService)
+ .genomDeTan(anyValueClass())
+
+ doAnswer { it.arguments[0] }.whenever(transformationService).transform(any<Mtb>())
+
+ whenever(consentProcessor.consentGatedCheckAndTryEmbedding(any())).thenReturn(true)
+
+ requestProcessor =
+ RequestProcessor(
+ pseudonymizeService,
+ transformationService,
+ sender,
+ requestService,
+ ObjectMapper(),
+ applicationEventPublisher,
+ AppConfigProperties(postInitialSubmissionBlock = true),
+ consentProcessor,
+ )
+
+ 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)
+
+ val requestCaptor = argumentCaptor<Request>()
+ verify(requestService, times(1)).save(requestCaptor.capture())
+ assertThat(requestCaptor.firstValue).isNotNull
+ assertThat(requestCaptor.firstValue.tan).isEqualTo(Tan("f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2"))
+ }
+
@Nested
inner class WithInitialSubmissionBlock {
@@ -656,6 +733,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.INITIAL,
RequestStatus.ERROR,
+ Tan.empty(),
Instant.parse("2026-01-05T09:00:00Z"),
submissionAccepted = false,
),
@@ -668,6 +746,7 @@ class RequestProcessorTest {
RequestType.MTB_FILE,
SubmissionType.INITIAL,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2026-01-05T10:00:00Z"),
submissionAccepted = false,
),
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
index fdb7578..d02a5fe 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/RequestServiceTest.kt
@@ -54,6 +54,7 @@ class RequestServiceTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-08-08T02:00:00Z"),
)
@@ -76,6 +77,7 @@ class RequestServiceTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant.parse("2023-07-07T00:00:00Z"),
),
Request(
@@ -87,6 +89,7 @@ class RequestServiceTest {
RequestType.DELETE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant.parse("2023-07-07T02:00:00Z"),
),
Request(
@@ -98,6 +101,7 @@ class RequestServiceTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.UNKNOWN,
+ Tan.empty(),
Instant.parse("2023-08-11T00:00:00Z"),
),
)
@@ -120,6 +124,7 @@ class RequestServiceTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant.parse("2023-07-07T00:00:00Z"),
),
Request(
@@ -131,6 +136,7 @@ class RequestServiceTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant.parse("2023-07-07T02:00:00Z"),
),
Request(
@@ -142,6 +148,7 @@ class RequestServiceTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.UNKNOWN,
+ Tan.empty(),
Instant.parse("2023-08-11T00:00:00Z"),
),
)
@@ -164,6 +171,7 @@ class RequestServiceTest {
RequestType.DELETE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-07-07T02:00:00Z"),
),
Request(
@@ -175,6 +183,7 @@ class RequestServiceTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.WARNING,
+ Tan.empty(),
Instant.parse("2023-08-08T00:00:00Z"),
),
)
@@ -212,6 +221,7 @@ class RequestServiceTest {
RequestType.DELETE,
SubmissionType.TEST,
RequestStatus.SUCCESS,
+ Tan.empty(),
Instant.parse("2023-07-07T02:00:00Z"),
)
diff --git a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
index 804b91c..3b09cc7 100644
--- a/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
+++ b/src/test/kotlin/dev/dnpm/etl/processor/services/ResponseProcessorTest.kt
@@ -55,6 +55,7 @@ class ResponseProcessorTest {
RequestType.MTB_FILE,
SubmissionType.TEST,
RequestStatus.UNKNOWN,
+ Tan.empty(),
)
@BeforeEach