From adfcf67d75156dd80aec0755b87cd65cf8d82dd7 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 17 Oct 2022 14:34:04 +0200 Subject: feat(mathing): join ZMR results and ERnP-to-ZMR-KITT results There are two ways to get a ZMR entry: 1. direct by ZMR 2. by ERnP marked as ZMR KITT entity In case of we only get a result by option 2, the ZMR entry has to be updated with eIDAS documents again --- .../eidas/v2/service/RegisterSearchService.java | 43 ++++++-- .../eidas/v2/test/tasks/InitialSearchTaskTest.java | 120 ++++++++++++++++++++- 2 files changed, 150 insertions(+), 13 deletions(-) diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java index b4f4098e..b947fbe3 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java @@ -38,11 +38,17 @@ public class RegisterSearchService { private static final Object ZMR = "ZMR"; private static final Object ERNP = "ERnP"; + private static final Object ERNP_KITT = "ERnP(ZMR-Kitt)"; + private static final String LOG_MSG_RESULTS = "Matching operation: {} results: " - + ZMR + ": {} | " + ERNP + ": {}"; + + ZMR + ": {} | " + ERNP + ": {} | " + ERNP_KITT + ": {}"; private static final String LOG_MSG_RESULTS_CLEARING = "Post-processing of register results find duplicated entries. " + "Remove {} entries from " + ERNP + " result."; + private static final String LOG_MSG_RESULTS_CLEARING_KITT = + "Post-processing of register results find duplicated entries. " + + "Remove {} entries from " + ERNP_KITT + " result."; + private static final String LOG_MSG_KITT = "Matching operation kitts entry on: {}"; @@ -98,7 +104,8 @@ public class RegisterSearchService { eidasData.getPseudonym(), eidasData.getCitizenCountryCode()); log.info(LOG_MSG_RESULTS, "seachByPersonalId", - resultsZmr.getPersonResult().size(), resultsErnp.getPersonResult().size()); + resultsZmr.getPersonResult().size(), resultsErnp.getPersonResult().size(), + resultsErnp.getZmrPersonResult().size()); return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultsErnp); @@ -129,7 +136,8 @@ public class RegisterSearchService { eidasData.getFamilyName(), eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode()); log.info(LOG_MSG_RESULTS, "seachByMDS", - resultsZmr.getPersonResult().size(), resultsErnp.getPersonResult().size()); + resultsZmr.getPersonResult().size(), resultsErnp.getPersonResult().size(), + resultsErnp.getZmrPersonResult().size()); return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultsErnp); @@ -168,7 +176,8 @@ public class RegisterSearchService { ccSpecificSearchReq, eidasData.getCitizenCountryCode()); log.info(LOG_MSG_RESULTS, "seachByCountrySpecifics", - resultsZmr.getPersonResult().size(), resultErnp.getPersonResult().size()); + resultsZmr.getPersonResult().size(), resultErnp.getPersonResult().size(), + resultErnp.getZmrPersonResult().size()); return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultErnp); @@ -205,7 +214,7 @@ public class RegisterSearchService { */ log.info(LOG_MSG_RESULTS, "seachByResidence", - resultsZmr.getPersonResult().size(), 0); + resultsZmr.getPersonResult().size(), 0, 0); return RegisterStatusResults.fromZmr(resultsZmr); @@ -452,16 +461,30 @@ public class RegisterSearchService { Set existingZmrPersons = result.getPersonResult().stream() .map(el -> el.getBpk()) .collect(Collectors.toSet()); - List ernpCleared = resultErnp.getPersonResult().stream() - .filter(el -> !existingZmrPersons.contains(el.getBpk())) - .collect(Collectors.toList()); + + // check active ERnP entries + List ernpCleared = resultErnp.getPersonResultStream() + .filter(el -> !existingZmrPersons.contains(el.getBpk())) + .collect(Collectors.toList()); if (ernpCleared.size() < resultErnp.getPersonResult().size()) { - log.info(LOG_MSG_RESULTS_CLEARING, resultErnp.getPersonResult().size() - ernpCleared.size()); + log.warn(LOG_MSG_RESULTS_CLEARING, resultErnp.getPersonResult().size() - ernpCleared.size()); } + // check ERnP to ZMR kitt entries and join results from ZMR client + List zmrCleared = Streams.concat( + resultErnp.getZmrPersonResultStream() + .filter(el -> !existingZmrPersons.contains(el.getBpk())), + result.getPersonResult().stream()) + .collect(Collectors.toList()); + if (zmrCleared.size() < result.getPersonResult().size() + resultErnp.getZmrPersonResult().size()) { + log.info(LOG_MSG_RESULTS_CLEARING, + result.getPersonResult().size() + resultErnp.getZmrPersonResult().size() - zmrCleared.size()); + + } + return new RegisterStatusResults(new RegisterOperationStatus(result.getProcessId()), - result.getPersonResult(), ernpCleared); + zmrCleared, ernpCleared); } static RegisterStatusResults fromErnp(RegisterOperationStatus status, ErnpRegisterResult updateErnp) { diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java index 4cfba521..1ce48a2e 100644 --- a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java +++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java @@ -331,6 +331,110 @@ public class InitialSearchTaskTest { } + /** + * Two matches by PersonalId found. + * + *
    + *
  • ZMR: one entry
  • + *
  • ERnP: one entry marked as ZMR kitt, but different bPK
  • + *
+ * + * @throws EidasSAuthenticationException + */ + @Test + @DirtiesContext + public void multiPersonalIdMatch_Zmr_ErnpKitt() throws EidasSAuthenticationException { + Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE)) + .thenReturn(new ZmrRegisterResult(Arrays.asList(randomRegisterResult(randomGivenName, randomBpk)), generateRandomProcessId())); + + String newRandomBpk = randomAlphabetic(10); + Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) + .thenReturn(ernpRegisterResult(Arrays.asList( + new ErnpPersonRegisterResult(randomRegisterResult(randomGivenName, newRandomBpk), true)))); + + // execute task + TaskExecutionException exception = assertThrows(TaskExecutionException.class, + () -> task.execute(pendingReq, executionContext)); + + // validate state + assertTrue("Wrong exception", (exception.getOriginalException() instanceof WorkflowException)); + assertTrue("Wrong flag 'manualFixNeeded'", + ((WorkflowException) exception.getOriginalException()).isRequiresManualFix()); + + } + + + /** + * Two matches by PersonalId found that are the same entity. + * + *
    + *
  • ZMR: one entry
  • + *
  • ERnP: one entry marked as ZMR kitt
  • + *
+ * + * @throws EidasSAuthenticationException + */ + @Test + @DirtiesContext + @SneakyThrows + public void multiPersonalIdMatch_Zmr_ErnpKitt_Same_Enity() throws EidasSAuthenticationException { + Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE)) + .thenReturn(new ZmrRegisterResult(Arrays.asList( + randomRegisterResult(randomGivenName, randomBpk)), generateRandomProcessId())); + Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) + .thenReturn(ernpRegisterResult(Arrays.asList( + new ErnpPersonRegisterResult(randomRegisterResult(randomGivenName, randomBpk), true)))); + + // execute test + task.execute(pendingReq, executionContext); + + // validate state + checkMatchingSuccessState(pendingReq, randomBpk, randomFamilyName, randomGivenName, randomBirthDate, DE); + + } + + /** + * Single matche by PersonalId found in ERnP, but it's a ZMR KITT entry. + *
    + *
  • ZMR: empty
  • + *
  • ERnP: one entry marked as ZMR kitt
  • + *
+ * + * @throws EidasSAuthenticationException + */ + @Test + @DirtiesContext + @SneakyThrows + public void singlePersonalIdMatch_ErnpKitt_UpdateRequird() throws EidasSAuthenticationException { + String oldGivenName = randomAlphabetic(10); + String placeOfBirth = randomAlphabetic(10); + RegisterResult firstErnpResult = randomRegisterResult(oldGivenName, randomBpk, placeOfBirth); + + Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE)) + .thenReturn(emptyZmrRegisterResult()); + Mockito.when(zmrClient.searchCountrySpecific(any(), any(), any())) + .thenThrow(new IllegalStateException("CountrySpecific search search should not be neccessary")); + Mockito.when(zmrClient.searchWithMds(any(), any(), any(), any(), any())) + .thenThrow(new IllegalStateException("MDS search should not be neccessary")); + Mockito.when(zmrClient.update(any(), any(), any())) + .thenReturn(zmrRegisterResult(firstErnpResult)); + + Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) + .thenReturn(ernpRegisterResult(Arrays.asList( + new ErnpPersonRegisterResult(firstErnpResult, true)))); + Mockito.when(ernpClient.searchWithMds(any(), any(), any(), any())) + .thenThrow(new IllegalStateException("MDS search should not be neccessary")); + Mockito.when(ernpClient.update(any(), any())) + .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); + + // execute test + task.execute(pendingReq, executionContext); + + // validate state + checkMatchingSuccessState(pendingReq, randomBpk, randomFamilyName, oldGivenName, randomBirthDate, DE); + + } + /** * Two matches by PersonalId * @@ -354,7 +458,7 @@ public class InitialSearchTaskTest { ((WorkflowException) exception.getOriginalException()).isRequiresManualFix()); } - + /** * Find to matches by PersonalId but they are the same person. */ @@ -817,11 +921,21 @@ public class InitialSearchTaskTest { @NotNull private ErnpRegisterResult ernpRegisterResult(List registerResult) { - return new ErnpRegisterResult(registerResult.stream() - .map(el -> new ErnpPersonRegisterResult(el, false)) + return new ErnpRegisterResult( + registerResult.stream() + .map(el -> { + if (el instanceof ErnpPersonRegisterResult) { + return (ErnpPersonRegisterResult)el; + + } else { + return new ErnpPersonRegisterResult(el, false); + + } + }) .collect(Collectors.toList())); } + @NotNull private RegisterResult randomRegisterResult() { return randomRegisterResult(randomGivenName, randomBpk); -- cgit v1.2.3