summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md7
-rw-r--r--build.gradle.kts4
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt20
-rw-r--r--src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt1
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt1
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt39
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt26
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt31
8 files changed, 122 insertions, 7 deletions
diff --git a/README.md b/README.md
index 2ef3b00..9b3cba9 100644
--- a/README.md
+++ b/README.md
@@ -112,9 +112,14 @@ Ab Version 2025.1 (Multi-Pseudonym Support)
* `APP_PSEUDONYMIZE_GPAS_USERNAME`: gPas Basic-Auth Benutzername
* `APP_PSEUDONYMIZE_GPAS_PASSWORD`: gPas Basic-Auth Passwort
* `APP_PSEUDONYMIZE_GPAS_PID_DOMAIN`: gPas Domänenname für Patienten ID
-* `APP_PSEUDONYMIZE_GPAS_GENOM_DE_TAN_DOMAIN`: gPas Multi-Pseudonym-Domäne für genomDE Vorgangsnummern (
+* `APP_PSEUDONYMIZE_GPAS_GENOM_DE_TAN_DOMAIN`: gPAS Multi-Pseudonym-Domäne für genomDE Vorgangsnummern (
Clinical data node)
+Soll anstelle der REST-Schnittstelle von gPAS die SOAP-Schnittstelle verwendet werden,
+so ist nicht die URI der gPAS-Instanz anzugeben, sondern der SOAP-Endpoint:
+
+* `APP_PSEUDONYMIZE_GPAS_SOAP_ENDPOINT`: SOAP-Endpoint der gPAS-Instanz (e.g. http://127.0.0.1:9990/gpas/gpasService)
+
### (Externe) Consent-Services
Consent-Services können konfiguriert werden.
diff --git a/build.gradle.kts b/build.gradle.kts
index 6a23aaf..738ed54 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -19,6 +19,7 @@ version = "0.12.0-SNAPSHOT"
var versions = mapOf(
"mtb-dto" to "0.1.0-SNAPSHOT",
"hapi-fhir" to "8.4.0",
+ "apache-cxf" to "4.1.3",
"mockito-kotlin" to "6.0.0",
"archunit" to "1.4.1",
// Webjars
@@ -91,6 +92,9 @@ dependencies {
implementation("org.webjars.npm:htmx.org:${versions["htmx.org"]}")
// Fix for CVE-2025-48924
implementation("org.apache.commons:commons-lang3:3.18.0")
+ // gPAS via Soap
+ implementation("org.apache.cxf:cxf-rt-frontend-jaxws:${versions["apache-cxf"]}")
+ implementation("org.apache.cxf:cxf-rt-transports-http:${versions["apache-cxf"]}")
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
runtimeOnly("org.postgresql:postgresql")
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt
index 66b62c8..5e25428 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/config/AppConfigurationTest.kt
@@ -29,6 +29,7 @@ import dev.dnpm.etl.processor.output.KafkaMtbFileSender
import dev.dnpm.etl.processor.output.RestMtbFileSender
import dev.dnpm.etl.processor.pseudonym.AnonymizingGenerator
import dev.dnpm.etl.processor.pseudonym.GpasPseudonymGenerator
+import dev.dnpm.etl.processor.pseudonym.GpasSoapPseudonymGenerator
import dev.dnpm.etl.processor.security.TokenRepository
import dev.dnpm.etl.processor.security.TokenService
import dev.dnpm.etl.processor.services.RequestProcessor
@@ -201,7 +202,8 @@ class AppConfigurationTest {
@Nested
@TestPropertySource(
properties = [
- "app.pseudonymize.generator=gpas"
+ "app.pseudonymize.generator=gpas",
+ "app.pseudonymize.gpas.uri=http://localhost/"
]
)
inner class AppConfigurationPseudonymizeGeneratorGpasTest(private val context: ApplicationContext) {
@@ -216,6 +218,22 @@ class AppConfigurationTest {
@Nested
@TestPropertySource(
properties = [
+ "app.pseudonymize.generator=gpas",
+ "app.pseudonymize.gpas.soap-endpoint=http://localhost/"
+ ]
+ )
+ inner class AppConfigurationPseudonymizeGeneratorGpasSoapTest(private val context: ApplicationContext) {
+
+ @Test
+ fun shouldUseConfiguredGenerator() {
+ assertThat(context.getBean(GpasSoapPseudonymGenerator::class.java)).isNotNull
+ }
+
+ }
+
+ @Nested
+ @TestPropertySource(
+ properties = [
"app.security.enable-tokens=true"
]
)
diff --git a/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt b/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt
index c2a8ba6..10f2359 100644
--- a/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt
+++ b/src/integrationTest/kotlin/dev/dnpm/etl/processor/pseudonym/GpasPseudonymGeneratorTest.kt
@@ -50,6 +50,7 @@ class GpasPseudonymGeneratorTest {
val retryTemplate = RetryTemplateBuilder().customPolicy(SimpleRetryPolicy(1)).build()
val gPasConfigProperties = GPasConfigProperties(
"https://localhost:9990/ttp-fhir/fhir/gpas",
+ null,
"test", "test2",
null,
null
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 395dbd2..fc0727f 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfigProperties.kt
@@ -47,6 +47,7 @@ data class PseudonymizeConfigProperties(
@ConfigurationProperties(GPasConfigProperties.NAME)
data class GPasConfigProperties(
val uri: String?,
+ val soapEndpoint: String?,
val patientDomain: String = "etl-processor",
val genomDeTanDomain: String = "ccdn",
val username: String?,
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
index b4fad3e..de302fd 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt
@@ -20,19 +20,17 @@
package dev.dnpm.etl.processor.config
import com.fasterxml.jackson.databind.ObjectMapper
-import dev.dnpm.etl.processor.consent.MtbFileConsentService
import dev.dnpm.etl.processor.consent.GicsConsentService
import dev.dnpm.etl.processor.consent.IConsentService
+import dev.dnpm.etl.processor.consent.MtbFileConsentService
import dev.dnpm.etl.processor.monitoring.*
-import dev.dnpm.etl.processor.pseudonym.AnonymizingGenerator
-import dev.dnpm.etl.processor.pseudonym.Generator
-import dev.dnpm.etl.processor.pseudonym.GpasPseudonymGenerator
-import dev.dnpm.etl.processor.pseudonym.PseudonymizeService
+import dev.dnpm.etl.processor.pseudonym.*
import dev.dnpm.etl.processor.security.TokenRepository
import dev.dnpm.etl.processor.security.TokenService
import dev.dnpm.etl.processor.services.ConsentProcessor
import dev.dnpm.etl.processor.services.Transformation
import dev.dnpm.etl.processor.services.TransformationService
+import org.apache.cxf.jaxws.JaxWsProxyFactoryBean
import org.slf4j.LoggerFactory
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
@@ -85,6 +83,37 @@ class AppConfiguration {
}
@ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
+ @Bean
+ fun gpasSoapProxyFactoryBean(gpasConfigProperties: GPasConfigProperties): JaxWsProxyFactoryBean {
+ val proxyFactory = JaxWsProxyFactoryBean()
+ proxyFactory.serviceClass = GpasSoapService::class.java
+ proxyFactory.address = gpasConfigProperties.soapEndpoint
+ return proxyFactory
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
+ @Bean
+ fun gpasSoapProxy(gpasConfigProperties: GPasConfigProperties): GpasSoapService {
+ return gpasSoapProxyFactoryBean(gpasConfigProperties).create() as GpasSoapService
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.soap-endpoint"])
+ @Bean
+ fun gpasSoapPseudonymGenerator(
+ configProperties: GPasConfigProperties,
+ retryTemplate: RetryTemplate,
+ gpasSoapService: GpasSoapService,
+ appFhirConfig: AppFhirConfig
+ ): Generator {
+ logger.info("Selected 'GpasSoapPseudonym Generator'")
+ return GpasSoapPseudonymGenerator(configProperties, retryTemplate, gpasSoapService, appFhirConfig)
+ }
+
+ @ConditionalOnProperty(value = ["app.pseudonymize.generator"], havingValue = "GPAS")
+ @ConditionalOnProperty(value = ["app.pseudonymize.gpas.uri"])
@Bean
fun gpasPseudonymGenerator(
configProperties: GPasConfigProperties,
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt
new file mode 100644
index 0000000..8215d23
--- /dev/null
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapPseudonymGenerator.kt
@@ -0,0 +1,26 @@
+package dev.dnpm.etl.processor.pseudonym
+
+import dev.dnpm.etl.processor.config.AppFhirConfig
+import dev.dnpm.etl.processor.config.GPasConfigProperties
+import org.springframework.retry.support.RetryTemplate
+
+class GpasSoapPseudonymGenerator(
+ private val gpasCfg: GPasConfigProperties,
+ private val retryTemplate: RetryTemplate,
+ private val gpasSoapService: GpasSoapService,
+ private val appFhirConfig: AppFhirConfig
+) : Generator {
+
+ override fun generate(id: String): String {
+ return retryTemplate.execute<String, Exception> {
+ gpasSoapService.getOrCreatePseudonymFor(id, gpasCfg.patientDomain)
+ }
+ }
+
+ override fun generateGenomDeTan(id: String): String {
+ return retryTemplate.execute<String, Exception> {
+ gpasSoapService.createPseudonymsFor(id, gpasCfg.genomDeTanDomain, 1).first()
+ }
+ }
+}
+
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt
new file mode 100644
index 0000000..0909924
--- /dev/null
+++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/GpasSoapService.kt
@@ -0,0 +1,31 @@
+package dev.dnpm.etl.processor.pseudonym
+
+import jakarta.jws.WebMethod
+import jakarta.jws.WebParam
+import jakarta.jws.WebResult
+import jakarta.jws.WebService
+import jakarta.xml.bind.annotation.XmlElementWrapper
+
+@WebService(
+ name = "PSNManagerBeanService",
+ targetNamespace ="http://psn.ttp.ganimed.icmvc.emau.org/"
+)
+interface GpasSoapService {
+
+ @WebMethod(operationName = "getOrCreatePseudonymFor")
+ @WebResult(name = "psn")
+ fun getOrCreatePseudonymFor(
+ @WebParam(name = "value") value: String,
+ @WebParam(name = "domainName") domainName: String
+ ): String
+
+ @WebMethod(operationName = "createPseudonymsFor")
+ @WebResult(name = "psn")
+ @XmlElementWrapper(name = "return")
+ fun createPseudonymsFor(
+ @WebParam(name = "value") value: String,
+ @WebParam(name = "domainName") domainName: String,
+ @WebParam(name = "number") minNumber: Int
+ ): List<String>
+
+} \ No newline at end of file