1
0
mirror of https://github.com/pcvolkmer/etl-processor.git synced 2025-07-02 22:42:55 +00:00

refactor: renamed misleading enum value TtpConsentStatus.IGNORED to TtpConsentStatus.UNKNOWN_CHECK_FILE also impl. ConsentCheckedIgnored has been renamed to ConsentCheckFileBased - since consent status should never be ignored.

Also renamed ICheckConsent.isConsented ICheckConsent.getTtpConsentStatus since new method name is more descriptive.
This commit is contained in:
Jakub Lidke
2025-05-12 11:25:45 +02:00
parent 542dc61811
commit 77df6f38ec
15 changed files with 59 additions and 53 deletions

View File

@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import de.ukw.ccc.bwhc.dto.*
import dev.dnpm.etl.processor.anyValueClass
import dev.dnpm.etl.processor.config.AppSecurityConfiguration
import dev.dnpm.etl.processor.consent.ConsentCheckedIgnored
import dev.dnpm.etl.processor.consent.ConsentCheckFileBased
import dev.dnpm.etl.processor.consent.TtpConsentStatus
import dev.dnpm.etl.processor.consent.ICheckConsent
import dev.dnpm.etl.processor.security.TokenRepository
@ -55,7 +55,7 @@ import org.springframework.test.web.servlet.post
classes = [
MtbFileRestController::class,
AppSecurityConfiguration::class,
ConsentCheckedIgnored::class, ICheckConsent::class
ConsentCheckFileBased::class, ICheckConsent::class
]
)
@MockitoBean(types = [TokenRepository::class, RequestProcessor::class])
@ -143,7 +143,7 @@ class MtbFileRestControllerTest {
status { isAccepted() }
}
verify(requestProcessor, times(1)).processDeletion(anyValueClass(), eq(TtpConsentStatus.IGNORED))
verify(requestProcessor, times(1)).processDeletion(anyValueClass(), eq(TtpConsentStatus.UNKNOWN_CHECK_FILE))
}
@Test

View File

@ -0,0 +1,9 @@
package dev.dnpm.etl.processor.consent;
public class ConsentCheckFileBased implements ICheckConsent{
@Override
public TtpConsentStatus getTtpConsentStatus(String personIdentifierValue) {
return TtpConsentStatus.UNKNOWN_CHECK_FILE;
}
}

View File

@ -1,9 +0,0 @@
package dev.dnpm.etl.processor.consent;
public class ConsentCheckedIgnored implements ICheckConsent{
@Override
public TtpConsentStatus isConsented(String personIdentifierValue) {
return TtpConsentStatus.IGNORED;
}
}

View File

@ -58,7 +58,7 @@ public class GicsConsentService implements ICheckConsent {
throw new IllegalArgumentException(
"gICS base URL is empty - should call gICS with false configuration.");
}
url = UriComponentsBuilder.fromHttpUrl(gIcsBaseUri).path(IS_CONSENTED_ENDPOINT)
url = UriComponentsBuilder.fromUriString(gIcsBaseUri).path(IS_CONSENTED_ENDPOINT)
.toUriString();
}
return url;
@ -147,7 +147,7 @@ public class GicsConsentService implements ICheckConsent {
}
@Override
public TtpConsentStatus isConsented(String personIdentifierValue) {
public TtpConsentStatus getTtpConsentStatus(String personIdentifierValue) {
var parameter = GicsConsentService.getIsConsentedParam(gIcsConfigProperties,
personIdentifierValue);
@ -176,10 +176,8 @@ public class GicsConsentService implements ICheckConsent {
return TtpConsentStatus.CONSENT_MISSING_OR_REJECTED;
}
} else if (response instanceof OperationOutcome outcome) {
log.error(
"failed to get consent status from ttp. probably configuration error. outcome: ",
fhirContext.newJsonParser().encodeToString(outcome));
log.error("failed to get consent status from ttp. probably configuration error. "
+ "outcome: '{}'", fhirContext.newJsonParser().encodeToString(outcome));
}
} catch (DataFormatException dfe) {

View File

@ -3,6 +3,6 @@ package dev.dnpm.etl.processor.consent;
public interface ICheckConsent {
TtpConsentStatus isConsented(String personIdentifierValue);
TtpConsentStatus getTtpConsentStatus(String personIdentifierValue);
}

View File

@ -7,12 +7,14 @@ public enum TtpConsentStatus {
CONSENTED,
CONSENT_MISSING_OR_REJECTED,
/**
* Due technical problems consent status is unknown
*/
FAILED_TO_ASK,
/**
* We assume received files are consented
* Consent status is validate via file property 'consent.status'
*/
IGNORED
UNKNOWN_CHECK_FILE
}

View File

@ -20,7 +20,7 @@
package dev.dnpm.etl.processor.config
import com.fasterxml.jackson.databind.ObjectMapper
import dev.dnpm.etl.processor.consent.ConsentCheckedIgnored
import dev.dnpm.etl.processor.consent.ConsentCheckFileBased
import dev.dnpm.etl.processor.consent.ICheckConsent
import dev.dnpm.etl.processor.consent.GicsConsentService
import dev.dnpm.etl.processor.monitoring.ConnectionCheckResult
@ -183,7 +183,7 @@ class AppConfiguration {
@Bean
@ConditionalOnMissingBean
fun constService(): ICheckConsent {
return ConsentCheckedIgnored()
return ConsentCheckFileBased()
}
@Bean

View File

@ -77,12 +77,12 @@ class KafkaInputListener(
} else {
logger.debug("Accepted MTB File and process deletion")
if (requestId.isBlank()) {
requestProcessor.processDeletion(patientId, TtpConsentStatus.IGNORED)
requestProcessor.processDeletion(patientId, TtpConsentStatus.UNKNOWN_CHECK_FILE)
} else {
requestProcessor.processDeletion(
patientId,
requestId,
TtpConsentStatus.IGNORED
TtpConsentStatus.UNKNOWN_CHECK_FILE
)
}
}

View File

@ -48,7 +48,7 @@ class MtbFileRestController(
@PostMapping(consumes = [MediaType.APPLICATION_JSON_VALUE])
fun mtbFile(@RequestBody mtbFile: MtbFile): ResponseEntity<Unit> {
val consentStatusBooleanPair = checkConsentStatus(mtbFile)
var ttpConsentStatus = consentStatusBooleanPair.first
val ttpConsentStatus = consentStatusBooleanPair.first
val isConsentOK = consentStatusBooleanPair.second
if (isConsentOK) {
logger.debug("Accepted MTB File (bwHC V1) for processing")
@ -63,14 +63,14 @@ class MtbFileRestController(
}
private fun checkConsentStatus(mtbFile: MtbFile): Pair<TtpConsentStatus, Boolean> {
var ttpConsentStatus = constService.isConsented(mtbFile.patient.id)
var ttpConsentStatus = constService.getTtpConsentStatus(mtbFile.patient.id)
val isConsentOK =
(ttpConsentStatus.equals(TtpConsentStatus.IGNORED) && mtbFile.consent.status == Consent.Status.ACTIVE) ||
(ttpConsentStatus.equals(TtpConsentStatus.UNKNOWN_CHECK_FILE) && mtbFile.consent.status == Consent.Status.ACTIVE) ||
ttpConsentStatus.equals(
TtpConsentStatus.CONSENTED
)
if (ttpConsentStatus.equals(TtpConsentStatus.IGNORED) && mtbFile.consent.status == Consent.Status.REJECTED) {
if (ttpConsentStatus.equals(TtpConsentStatus.UNKNOWN_CHECK_FILE) && mtbFile.consent.status == Consent.Status.REJECTED) {
// in case ttp check is disabled - we propagate rejected status anyway
ttpConsentStatus = TtpConsentStatus.CONSENT_MISSING_OR_REJECTED
}
@ -87,7 +87,7 @@ class MtbFileRestController(
@DeleteMapping(path = ["{patientId}"])
fun deleteData(@PathVariable patientId: String): ResponseEntity<Unit> {
logger.debug("Accepted patient ID to process deletion")
requestProcessor.processDeletion(PatientId(patientId), TtpConsentStatus.IGNORED)
requestProcessor.processDeletion(PatientId(patientId), TtpConsentStatus.UNKNOWN_CHECK_FILE)
return ResponseEntity.accepted().build()
}

View File

@ -140,7 +140,7 @@ class RequestProcessor(
val requestStatus: RequestStatus = when (isConsented) {
TtpConsentStatus.CONSENT_MISSING_OR_REJECTED -> RequestStatus.NO_CONSENT
TtpConsentStatus.FAILED_TO_ASK -> RequestStatus.ERROR
TtpConsentStatus.CONSENTED, TtpConsentStatus.IGNORED -> RequestStatus.UNKNOWN
TtpConsentStatus.CONSENTED, TtpConsentStatus.UNKNOWN_CHECK_FILE -> RequestStatus.UNKNOWN
}
requestService.save(

View File

@ -48,7 +48,7 @@ public class GicsConsentServiceTest {
}
@Test
void isConsented() {
void getTtpConsentStatus() {
final Parameters responseConsented = new Parameters().addParameter(
new ParametersParameterComponent().setName("consented")
.setValue(new BooleanType().setValue(true)));
@ -59,7 +59,7 @@ public class GicsConsentServiceTest {
.encodeResourceToString(responseConsented),
MediaType.APPLICATION_JSON));
var consentStatus = gicsConsentService.isConsented("123456");
var consentStatus = gicsConsentService.getTtpConsentStatus("123456");
assertThat(consentStatus).isEqualTo(TtpConsentStatus.CONSENTED);
}
@ -76,7 +76,7 @@ public class GicsConsentServiceTest {
.encodeResourceToString(responseRevoced),
MediaType.APPLICATION_JSON));
var consentStatus = gicsConsentService.isConsented("123456");
var consentStatus = gicsConsentService.getTtpConsentStatus("123456");
assertThat(consentStatus).isEqualTo(TtpConsentStatus.CONSENT_MISSING_OR_REJECTED);
}
@ -94,7 +94,7 @@ public class GicsConsentServiceTest {
.encodeResourceToString(responseErrorOutcome),
MediaType.APPLICATION_JSON));
var consentStatus = gicsConsentService.isConsented("123456");
var consentStatus = gicsConsentService.getTtpConsentStatus("123456");
assertThat(consentStatus).isEqualTo(TtpConsentStatus.FAILED_TO_ASK);
}

View File

@ -94,7 +94,7 @@ class KafkaInputListenerTest {
verify(requestProcessor, times(1)).processDeletion(
anyValueClass(),
eq(TtpConsentStatus.IGNORED)
eq(TtpConsentStatus.UNKNOWN_CHECK_FILE)
)
}
@ -149,7 +149,7 @@ class KafkaInputListenerTest {
)
)
verify(requestProcessor, times(1)).processDeletion(anyValueClass(), anyValueClass(), eq(
TtpConsentStatus.IGNORED))
TtpConsentStatus.UNKNOWN_CHECK_FILE))
}
@Test
@ -181,7 +181,7 @@ class KafkaInputListenerTest {
)
)
verify(requestProcessor, times(0)).processDeletion(anyValueClass(), anyValueClass(), eq(
TtpConsentStatus.IGNORED))
TtpConsentStatus.UNKNOWN_CHECK_FILE))
}
}

View File

@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import de.ukw.ccc.bwhc.dto.*
import de.ukw.ccc.bwhc.dto.Consent.Status
import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.consent.ConsentCheckedIgnored
import dev.dnpm.etl.processor.consent.ConsentCheckFileBased
import dev.dnpm.etl.processor.consent.GicsConsentService
import dev.dnpm.etl.processor.consent.TtpConsentStatus
import dev.dnpm.etl.processor.services.RequestProcessor
@ -67,7 +67,9 @@ class MtbFileRestControllerTest {
@Mock requestProcessor: RequestProcessor
) {
this.requestProcessor = requestProcessor
val controller = MtbFileRestController(requestProcessor, ConsentCheckedIgnored())
val controller = MtbFileRestController(requestProcessor,
ConsentCheckFileBased()
)
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build()
}
@ -113,7 +115,7 @@ class MtbFileRestControllerTest {
verify(requestProcessor, times(1)).processDeletion(
anyValueClass(),
org.mockito.kotlin.eq(TtpConsentStatus.IGNORED)
org.mockito.kotlin.eq(TtpConsentStatus.UNKNOWN_CHECK_FILE)
)
}
}
@ -147,7 +149,7 @@ class MtbFileRestControllerTest {
@ValueSource(strings = ["ACTIVE", "REJECTED"])
fun shouldProcessPostRequest(status: String) {
whenever(gicsConsentService.isConsented(any())).thenReturn(TtpConsentStatus.CONSENTED)
whenever(gicsConsentService.getTtpConsentStatus(any())).thenReturn(TtpConsentStatus.CONSENTED)
mockMvc.post("/mtbfile") {
content =
@ -167,7 +169,7 @@ class MtbFileRestControllerTest {
@ValueSource(strings = ["ACTIVE", "REJECTED"])
fun shouldProcessPostRequestWithRejectedConsent(status: String) {
whenever(gicsConsentService.isConsented(any())).thenReturn(TtpConsentStatus.CONSENT_MISSING_OR_REJECTED)
whenever(gicsConsentService.getTtpConsentStatus(any())).thenReturn(TtpConsentStatus.CONSENT_MISSING_OR_REJECTED)
mockMvc.post("/mtbfile") {
content =
@ -197,9 +199,9 @@ class MtbFileRestControllerTest {
verify(requestProcessor, times(1)).processDeletion(
anyValueClass(),
org.mockito.kotlin.eq(TtpConsentStatus.IGNORED)
org.mockito.kotlin.eq(TtpConsentStatus.UNKNOWN_CHECK_FILE)
)
verify(gicsConsentService, times(0)).isConsented(any())
verify(gicsConsentService, times(0)).getTtpConsentStatus(any())
}
}
@ -217,7 +219,9 @@ class MtbFileRestControllerTest {
@Mock requestProcessor: RequestProcessor
) {
this.requestProcessor = requestProcessor
val controller = MtbFileRestController(requestProcessor, ConsentCheckedIgnored())
val controller = MtbFileRestController(requestProcessor,
ConsentCheckFileBased()
)
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build()
}
@ -264,7 +268,7 @@ class MtbFileRestControllerTest {
verify(requestProcessor, times(1)).processDeletion(
anyValueClass(), org.mockito.kotlin.eq(
TtpConsentStatus.IGNORED
TtpConsentStatus.UNKNOWN_CHECK_FILE
)
)
}
@ -282,7 +286,9 @@ class MtbFileRestControllerTest {
@Mock requestProcessor: RequestProcessor
) {
this.requestProcessor = requestProcessor
val controller = MtbFileRestController(requestProcessor, ConsentCheckedIgnored())
val controller = MtbFileRestController(requestProcessor,
ConsentCheckFileBased()
)
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build()
}

View File

@ -344,7 +344,7 @@ class RequestProcessorTest {
MtbFileSender.Response(status = RequestStatus.UNKNOWN)
}.whenever(sender).send(any<DeleteRequest>())
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED)
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE)
val requestCaptor = argumentCaptor<Request>()
verify(requestService, times(1)).save(requestCaptor.capture())
@ -362,7 +362,7 @@ class RequestProcessorTest {
MtbFileSender.Response(status = RequestStatus.SUCCESS)
}.whenever(sender).send(any<DeleteRequest>())
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED)
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@ -380,7 +380,7 @@ class RequestProcessorTest {
MtbFileSender.Response(status = RequestStatus.ERROR)
}.whenever(sender).send(any<DeleteRequest>())
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED)
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE)
val eventCaptor = argumentCaptor<ResponseEvent>()
verify(applicationEventPublisher, times(1)).publishEvent(eventCaptor.capture())
@ -392,7 +392,7 @@ class RequestProcessorTest {
fun testShouldSendDeleteRequestWithPseudonymErrorAndSaveErrorRequestStatus() {
doThrow(RuntimeException()).whenever(pseudonymizeService).patientPseudonym(anyValueClass())
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.IGNORED)
this.requestProcessor.processDeletion(TEST_PATIENT_ID, isConsented = TtpConsentStatus.UNKNOWN_CHECK_FILE)
val requestCaptor = argumentCaptor<Request>()
verify(requestService, times(1)).save(requestCaptor.capture())