diff options
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java')
-rw-r--r-- | eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java | 328 |
1 files changed, 258 insertions, 70 deletions
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java index 6b524e36..166ffafb 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java @@ -1,18 +1,28 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.service; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult; +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nonnull; + +import org.jetbrains.annotations.Nullable; +import org.springframework.stereotype.Service; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.IZmrClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient.ZmrRegisterResult; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; import at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.IErnpClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ZmrCommunicationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.CountrySpecificDetailSearchProcessor; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.Collections; -import java.util.List; @Slf4j @Service("registerSearchService") @@ -21,99 +31,277 @@ public class RegisterSearchService { private final IZmrClient zmrClient; private final IErnpClient ernpClient; - public RegisterSearchService(IZmrClient zmrClient, IErnpClient ernpClient) { + private final List<CountrySpecificDetailSearchProcessor> handlers; + + /** + * Service that combines ZMR and ERnP register search operations. + * + * @param handlers Available country-specific search processors + * @param zmrClient ZMR client + * @param ernpClient ERnP client + */ + public RegisterSearchService(List<CountrySpecificDetailSearchProcessor> handlers, IZmrClient zmrClient, + IErnpClient ernpClient) { this.zmrClient = zmrClient; this.ernpClient = ernpClient; + this.handlers = handlers; + log.info("Init with #{} search services for country-specific details", handlers.size()); + } /** - * Automatic process to fix the register entries. + * Search with Person Identifier (eIDAS Pseudonym) in ZMR and ERnP. * - * @param initialSearchResult Result of initial register search - * @param specificSearchResult Result of last register search - * @param eidasData Received eidas data - * @param pendingReq Pending request - * @return The bpk - * @throws TaskExecutionException if an error occurs during the register update + * @param eidasData Received eIDAS data + * @throws WorkflowException In case of a register interaction error */ - public String step7aKittProcess(MergedRegisterSearchResult initialSearchResult, - MergedRegisterSearchResult specificSearchResult, - SimpleEidasData eidasData, - IRequest pendingReq) throws TaskExecutionException { - log.trace("Starting step7aKittProcess"); - // TODO verify with which data this method gets called + @Nonnull + public RegisterSearchResult searchWithPersonIdentifier(SimpleEidasData eidasData) + throws WorkflowException { try { - if (initialSearchResult.getResultCount() != 0) { - throw new WorkflowException("initialSearchResult.getResultCount() != 0"); - } - if (specificSearchResult.getResultCount() != 1) { - throw new WorkflowException("specificSearchResult.getResultCount() != 1"); - } - if (specificSearchResult.getResultsZmr().size() == 1) { - zmrClient.update(specificSearchResult.getResultsZmr().get(0), eidasData); - } - if (specificSearchResult.getResultsErnp().size() == 1) { - ernpClient.update(specificSearchResult.getResultsErnp().get(0), eidasData); - } - return specificSearchResult.getBpk(); - } catch (WorkflowException e) { - throw new TaskExecutionException(pendingReq, "Step7a failed.", e); + final ZmrRegisterResult resultsZmr = zmrClient.searchWithPersonIdentifier( + null, eidasData.getPersonalIdentifier()); + final List<RegisterResult> resultsErnp = ernpClient.searchWithPersonIdentifier( + eidasData.getPersonalIdentifier()); + + return new RegisterSearchResult(new RegisterOperationStatus(resultsZmr.getProcessId()), + resultsZmr.getPersonResult(), resultsErnp); + + } catch (final EidasSAuthenticationException e) { + throw new WorkflowException("searchWithPersonalIdentifier", e.getMessage(), + !(e instanceof ZmrCommunicationException), e); + } } /** * Search with MDS (Given Name, Family Name, Date of Birth) in ZMR and ERnP. + * + * @param operationStatus Current register-operation status that contains processing informations + * @param eidasData Received eIDAS data + * @throws WorkflowException In case of a register interaction error */ - public MergedRegisterSearchResult searchWithMds(SimpleEidasData eidasData) { - List<RegisterResult> resultsZmr = - zmrClient.searchWithMds(eidasData.getGivenName(), eidasData.getFamilyName(), eidasData.getDateOfBirth()); - List<RegisterResult> resultsErnp = - ernpClient.searchWithMds(eidasData.getGivenName(), eidasData.getFamilyName(), eidasData.getDateOfBirth()); - return new MergedRegisterSearchResult(resultsZmr, resultsErnp); + @Nonnull + public RegisterSearchResult searchWithMds(RegisterOperationStatus operationStatus, SimpleEidasData eidasData) + throws WorkflowException { + try { + final ZmrRegisterResult resultsZmr = + zmrClient.searchWithMds(operationStatus.getZmrProcessId(), eidasData.getGivenName(), + eidasData.getFamilyName(), eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode()); + + final List<RegisterResult> resultsErnp = + ernpClient.searchWithMds(eidasData.getGivenName(), eidasData.getFamilyName(), eidasData + .getDateOfBirth()); + + return new RegisterSearchResult(new RegisterOperationStatus(resultsZmr.getProcessId()), + resultsZmr.getPersonResult(), resultsErnp); + + } catch (final EidasSAuthenticationException e) { + throw new WorkflowException("searchWithMDSOnly", e.getMessage(), + !(e instanceof ZmrCommunicationException), e); + + } } /** - * Search with Person Identifier (eIDAS Pseudonym) in ZMR and ERnP. + * Search with country-specific parameters based on information from available + * {@link CountrySpecificDetailSearchProcessor} implementations. + * + * @param operationStatus Current register-operation status that contains processing informations + * @param eidasData Receive eIDAS eID information + * @return Results from ZMR or ERnP search + * @throws WorkflowException In case of a register interaction error */ - public MergedRegisterSearchResult searchWithPersonIdentifier(SimpleEidasData eidasData) { - List<RegisterResult> resultsZmr = zmrClient.searchWithPersonIdentifier(eidasData.getPseudonym()); - List<RegisterResult> resultsErnp = ernpClient.searchWithPersonIdentifier(eidasData.getPseudonym()); - return new MergedRegisterSearchResult(resultsZmr, resultsErnp); + @Nonnull + public RegisterSearchResult searchWithCountrySpecifics(RegisterOperationStatus operationStatus, + SimpleEidasData eidasData) throws WorkflowException { + try { + @Nullable + final CountrySpecificDetailSearchProcessor ccSpecificProcessor = findSpecificProcessor(eidasData); + if (ccSpecificProcessor != null) { + log.debug("Selecting country-specific search processor: {}", ccSpecificProcessor.getName()); + final ZmrRegisterResult resultsZmr = + zmrClient.searchCountrySpecific(operationStatus.getZmrProcessId(), + ccSpecificProcessor.generateSearchRequest(eidasData), + eidasData.getCitizenCountryCode()); + + // TODO: add search procesfor for ERnP searching + return new RegisterSearchResult(operationStatus, resultsZmr.getPersonResult(), Collections.emptyList()); + + } else { + return new RegisterSearchResult(operationStatus, Collections.emptyList(), Collections.emptyList()); + + } + + } catch (final EidasSAuthenticationException e) { + throw new WorkflowException("searchWithCountrySpecifics", e.getMessage(), + !(e instanceof ZmrCommunicationException), e); + + } } /** - * Search with Tax Number in ZMR and ERnP. + * Search with BPK-ZP in BMR and ERnP. */ - public MergedRegisterSearchResult searchItSpecific(SimpleEidasData eidasData) { - List<RegisterResult> resultsZmr = zmrClient.searchItSpecific(eidasData.getTaxNumber()); - List<RegisterResult> resultsErnb = ernpClient.searchItSpecific(eidasData.getTaxNumber()); - return new MergedRegisterSearchResult(resultsZmr, resultsErnb); + public RegisterSearchResult searchWithBpkZp(RegisterOperationStatus operationStatus, String bpkZp) { + final ZmrRegisterResult resultsZmr = zmrClient.searchWithBpkZp( + operationStatus.getZmrProcessId(), bpkZp); + final List<RegisterResult> resultsErnp = ernpClient.searchWithBpkZp(bpkZp); + return new RegisterSearchResult(operationStatus, resultsZmr.getPersonResult(), resultsErnp); + } /** - * Search with Given Name, Family Name, Date of Birth, Place of Birth and Birth Name in ZMR and ERnP. + * Search with residence infos. + * + * @param operationStatus Current register-operation status that contains processing informations + * @param zipcode Provided Zipcode + * @param city Provided City + * @param street Provided street + * @return Results from ZMR or ERnP search */ - public MergedRegisterSearchResult searchDeSpecific(SimpleEidasData eidasData) { - List<RegisterResult> resultsZmr = - zmrClient.searchDeSpecific(eidasData.getGivenName(), eidasData.getFamilyName(), eidasData.getDateOfBirth(), - eidasData.getPlaceOfBirth(), eidasData.getBirthName()); - List<RegisterResult> resultsErnb = - ernpClient.searchDeSpecific(eidasData.getGivenName(), eidasData.getFamilyName(), eidasData.getDateOfBirth(), - eidasData.getPlaceOfBirth(), eidasData.getBirthName()); - return new MergedRegisterSearchResult(resultsZmr, resultsErnb); + public RegisterSearchResult searchWithResidence(RegisterOperationStatus operationStatus, SimpleEidasData eidasData, + String zipcode, String city, String street) { + final ZmrRegisterResult resultsZmr = zmrClient.searchWithResidenceData( + operationStatus.getZmrProcessId(), eidasData.getGivenName(), eidasData.getFamilyName(), + eidasData.getDateOfBirth(), zipcode, city, street); + return new RegisterSearchResult(operationStatus, resultsZmr.getPersonResult(), Collections.emptyList()); + } /** - * Search with BPK-ZP in BMR and ERnP. + * Automatic process to fix the register entries. + * + * @param specificSearchResult Result of last register search + * @param eidasData Received eidas data + */ + public void step7aKittProcess(RegisterSearchResult specificSearchResult, + SimpleEidasData eidasData) throws WorkflowException { + log.trace("Starting step7aKittProcess"); + // TODO verify with which data this method gets called + if (specificSearchResult.getResultCount() != 1) { + throw new WorkflowException("step7aKittProcess", "getResultCount() != 1"); + + } + + if (specificSearchResult.getResultsZmr().size() == 1) { + zmrClient.update(specificSearchResult.getOperationStatus().getZmrProcessId(), + + specificSearchResult.getResultsZmr().get(0), eidasData); + } + + if (specificSearchResult.getResultsErnp().size() == 1) { + ernpClient.update(specificSearchResult.getResultsErnp().get(0), eidasData); + + } + + } + + @Nullable + private CountrySpecificDetailSearchProcessor findSpecificProcessor(SimpleEidasData eidasData) { + final String citizenCountry = eidasData.getCitizenCountryCode(); + for (final CountrySpecificDetailSearchProcessor processor : handlers) { + if (processor.canHandle(citizenCountry, eidasData)) { + log.debug("Found suitable search handler for {} by using: {}", citizenCountry, processor.getName()); + return processor; + } + } + return null; + } + + /** + * Register releated information that are needed for any request. + * + * @author tlenz + * */ - public MergedRegisterSearchResult searchWithBpkZp(String bpkZp) { - List<RegisterResult> resultsZmr = zmrClient.searchWithBpkZp(bpkZp); - List<RegisterResult> resultsErnp = ernpClient.searchWithBpkZp(bpkZp); - return new MergedRegisterSearchResult(resultsZmr, resultsErnp); + @AllArgsConstructor + @Getter + public static class RegisterOperationStatus { + + /** + * ZMR internal processId that is required for any further request in the same process. + */ + private BigInteger zmrProcessId; + + } + + /** + * Response container for {@link RegisterSearchService}. + * + * @author tlenz + * + */ + @Getter + @RequiredArgsConstructor + public static class RegisterSearchResult { + + /** + * Mark the register result finished. + */ + @Setter + private boolean matchingFinished = false; + + /** + * Operation status for this result. + */ + private final RegisterOperationStatus operationStatus; + + /** + * Current ZMR search result. + */ + private final List<RegisterResult> resultsZmr; + + /** + * Current ERnP search result. + */ + private final List<RegisterResult> resultsErnp; + + + /** + * Get sum of ZMR and ERnP results. + * + * @return number of results + */ + public int getResultCount() { + return resultsZmr.size() + resultsErnp.size(); + } + + /** + * Verifies that there is only one match and returns the bpk. + * + * @return bpk bpk of the match + * @throws WorkflowException if multiple results have been found or matching is not marked as finished + */ + public String getBpk() throws WorkflowException { + if (getResultCount() != 1 || !matchingFinished) { + throw new WorkflowException("readRegisterResults", + matchingFinished ? "getResultCount() != 1" : "matching prozess not finished yet"); + + } + return getResult().getBpk(); + } - public MergedRegisterSearchResult searchWithResidence(String zipcode, String city, String street) { - List<RegisterResult> resultsZmr = zmrClient.searchWithResidenceData(zipcode, city, street); - return new MergedRegisterSearchResult(resultsZmr, Collections.emptyList()); + /** + * Returns the results, if there is exactly one, throws exception otherwise. + * + * @return The result + * @throws WorkflowException Results does not contain exactly one result + */ + public RegisterResult getResult() throws WorkflowException { + if (getResultCount() != 1) { + throw new WorkflowException("readRegisterResults", "getResultCount() != 1"); + } + if (resultsZmr.size() == 1) { + return resultsZmr.get(0); + + } else { + return resultsErnp.get(0); + + } + } + } + } |