diff options
| author | Thomas <> | 2022-07-05 17:49:34 +0200 | 
|---|---|---|
| committer | Thomas <> | 2022-07-05 17:49:34 +0200 | 
| commit | b5766d8107d6e557921f9a694893a1284963ef16 (patch) | |
| tree | 708e695bb0c90d958ef0e3cde6008169fb683893 /modules/authmodule-eIDAS-v2/src | |
| parent | 154f7f2a9c8a33d3fedf341df2be62d8404ff77f (diff) | |
| parent | 48695aa01a86890990dc4e42b9d44493ec840b25 (diff) | |
| download | National_eIDAS_Gateway-b5766d8107d6e557921f9a694893a1284963ef16.tar.gz National_eIDAS_Gateway-b5766d8107d6e557921f9a694893a1284963ef16.tar.bz2 National_eIDAS_Gateway-b5766d8107d6e557921f9a694893a1284963ef16.zip | |
Merge branch 'nightlybuild' into feature/ms_proxy_service
Diffstat (limited to 'modules/authmodule-eIDAS-v2/src')
16 files changed, 288 insertions, 47 deletions
| diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java index e766fc49..3c41bf0a 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java @@ -128,7 +128,15 @@ public class Constants {    public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_NAME = CONIG_PROPS_EIDAS_COMMON_CLIENT        + ".ssl.trustStore.name"; -     +  /** Enable / Disable matching based on address search. **/ +  public static final String CONFIG_PROP_MATCHING_BY_ADDRESS = +      EidasConstants.CONIG_PROPS_EIDAS_PREFIX + ".matching.byaddress.enable"; +   +  public static final String CONFIG_PROP_MATCHING_BY_ADDRESS_MAX_RESULTS =  +      EidasConstants.CONIG_PROPS_EIDAS_PREFIX + ".matching.byaddress.maxresults"; +  public static final String DEFAULT_MATCHING_BY_ADDRESS_MAX_RESULTS = "250";  +   +      // ZMR Client configuration properties    public static final String CONIG_PROPS_EIDAS_ZMRCLIENT =         EidasConstants.CONIG_PROPS_EIDAS_PREFIX + ".zmrclient"; @@ -312,6 +320,7 @@ public class Constants {    // UI options +  public static final String HTML_FORM_ENABLE_MATCHING_BY_ADDRESS_SEARCH = "enableMatchingByAddressSearch";    public static final String HTML_FORM_CREATE_NEW_ERNP_ENTRY = "createNewErnpEntry";    public static final String HTML_FORM_ADVANCED_MATCHING_FAILED = "advancedMatchingFailed";    public static final String HTML_FORM_ADVANCED_MATCHING_FAILED_REASON =  diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java index 6f49c700..a08128d3 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java @@ -25,6 +25,7 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.controller;  import java.util.Collection;  import java.util.Collections; +import java.util.Comparator;  import java.util.List;  import java.util.Set;  import java.util.stream.Collectors; @@ -40,12 +41,14 @@ import org.springframework.web.bind.annotation.RequestMethod;  import org.springframework.web.bind.annotation.RequestParam;  import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrAddressSoapClient;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;  import at.gv.bmi.namespace.zmr_su.zrm._20040201_.address.Adressdaten;  import at.gv.e_government.reference.namespace.persondata.de._20040201.PostAdresseTyp;  import at.gv.e_government.reference.namespace.persondata.de._20040201.ZustelladresseTyp;  import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration;  import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy;  import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException;  import lombok.AllArgsConstructor; @@ -67,17 +70,19 @@ public class AdresssucheController {    public static final String PARAM_VILLAGE = "village";    public static final String PARAM_STREET = "street";    public static final String PARAM_NUMBER = "number"; -     + +  @Autowired IConfiguration basicConfig; +      @Autowired    private ZmrAddressSoapClient client;    @Autowired    private IPendingRequestIdGenerationStrategy pendingReqGeneration; -   +    /**     * Performs search for addresses in ZMR.     */ -  @RequestMapping(value = {MsEidasNodeConstants.ENDPOINT_RESIDENCY_SEARCH}, method = {RequestMethod.POST}) +  @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_RESIDENCY_SEARCH }, method = { RequestMethod.POST })    public ResponseEntity<AdresssucheResult> search(        @RequestParam(PARAM_POSTLEITZAHL) String postleitzahl,        @RequestParam(PARAM_MUNIPICALITY) String municipality, @@ -90,26 +95,26 @@ public class AdresssucheController {          municipality.replaceAll("[\r\n]", ""),          village.replaceAll("[\r\n]", ""),          street.replaceAll("[\r\n]", ""), -        number.replaceAll("[\r\n]", ""));     +        number.replaceAll("[\r\n]", ""));      try {        pendingReqGeneration.validateAndGetPendingRequestId(pendingId); -       -    } catch (PendingReqIdValidationException e) { + +    } catch (final PendingReqIdValidationException e) {        log.warn("Search with pendingId '{}' is not valid", pendingId.replaceAll("[\r\n]", ""));        return ResponseEntity.badRequest().build(); -       +      } -     +      try { -      Adressdaten searchInput = buildSearchInput(postleitzahl, municipality, village, street, number); -      ZmrAddressSoapClient.AddressInfo searchOutput = client.searchAddress(searchInput); -      AdresssucheResult output = buildResponse(searchOutput); +      final Adressdaten searchInput = buildSearchInput(postleitzahl, municipality, village, street, number); +      final ZmrAddressSoapClient.AddressInfo searchOutput = client.searchAddress(searchInput); +      final AdresssucheResult output = buildResponse(searchOutput);        return ResponseEntity.ok(output); -       -    } catch (EidasSAuthenticationException e) { + +    } catch (final EidasSAuthenticationException e) {        log.warn("Search failed", e);        return ResponseEntity.badRequest().build(); -       +      }    } @@ -117,27 +122,45 @@ public class AdresssucheController {      if (searchOutput.getPersonResult().isEmpty()) {        log.warn("No result from ZMR");        return new AdresssucheResult(Collections.emptyList(), 0); -       +      } -     +      log.info("Result level is {}", searchOutput.getLevel()); -    Set<AdresssucheOutput> result = searchOutput.getPersonResult().stream() +    final Set<AdresssucheOutput> result = searchOutput.getPersonResult().stream()          .map(Adressdaten::getPostAdresse)          .map(it -> new AdresssucheOutput(it.getPostleitzahl(), it.getGemeinde(), it.getOrtschaft(),              it.getZustelladresse().getStrassenname(), it.getZustelladresse().getOrientierungsnummer()))          .collect(Collectors.toSet());      // TODO Add configuration option for the limit of 30 -    List<AdresssucheOutput> sorted = result.stream().sorted().limit(30).collect(Collectors.toList()); -    return new AdresssucheResult(sorted, result.size()); +         +    final List<AdresssucheOutput> sorted = result.stream() +        .sorted() +        .limit(getMaxResults()) +        .collect(Collectors.toList()); +    return new AdresssucheResult(sorted, result.size()); + +  } + +  private long getMaxResults() { +    String maxSearchResults = basicConfig.getBasicConfiguration( +        Constants.CONFIG_PROP_MATCHING_BY_ADDRESS_MAX_RESULTS, +        Constants.DEFAULT_MATCHING_BY_ADDRESS_MAX_RESULTS); +    try { +      return Long.valueOf(maxSearchResults); +       +    } catch (Exception e) { +      log.warn("Invalid number of max. addressSearchResults. Using default value", e); +      return Long.valueOf(Constants.DEFAULT_MATCHING_BY_ADDRESS_MAX_RESULTS); +    }    }    private Adressdaten buildSearchInput(String postleitzahl, -                                       String municipality, -                                       String village, -                                       String street, -                                       String number) { -    PostAdresseTyp postAdresse = new PostAdresseTyp(); +      String municipality, +      String village, +      String street, +      String number) { +    final PostAdresseTyp postAdresse = new PostAdresseTyp();      if (StringUtils.isNotBlank(postleitzahl)) {        postAdresse.setPostleitzahl(postleitzahl);      } @@ -148,7 +171,7 @@ public class AdresssucheController {        postAdresse.setOrtschaft(village);      }      if (StringUtils.isNotBlank(street) || StringUtils.isNotBlank(number)) { -      ZustelladresseTyp zustelladresse = new ZustelladresseTyp(); +      final ZustelladresseTyp zustelladresse = new ZustelladresseTyp();        if (StringUtils.isNotBlank(street)) {          zustelladresse.setStrassenname(street);        } @@ -157,10 +180,10 @@ public class AdresssucheController {        }        postAdresse.setZustelladresse(zustelladresse);      } -    Adressdaten searchInput = new Adressdaten(); +    final Adressdaten searchInput = new Adressdaten();      searchInput.setPostAdresse(postAdresse);      return searchInput; -     +    }    @Data @@ -187,9 +210,41 @@ public class AdresssucheController {            .append(this.municipality, o.municipality)            .append(this.village, o.village)            .append(this.street, o.street) -          .append(this.number, o.number) + +          /* +           * TODO: implement better sort method, because current version results to 1, 10, +           * 11, .... 2, 20, 21 +           */ +          .appendSuper(getCustomIntegerComperatpr().compare(this.number, o.number)) +            .toComparison();      } + +    private Comparator<String> getCustomIntegerComperatpr() { +      return new Comparator<String>() { +        @Override +        public int compare(String o1, String o2) { +          return extractInt(o1) - extractInt(o2); +        } + +        int extractInt(String s) { +          if (StringUtils.isNotEmpty(s)) { +            final String num = s.replaceAll("\\D", ""); +            try { +              // return 0 if no digits found +              return num.isEmpty() ? 0 : Integer.parseInt(num); +               +            } catch (Exception e) { +              log.info("Can not parse number from ZMR", e); +               +            }           +          }  +                       +          return 0; +                       +        } +      }; +    }    }  } diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SelectedLoginMethod.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SelectedLoginMethod.java index 70904e4f..c8a2da88 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SelectedLoginMethod.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SelectedLoginMethod.java @@ -1,5 +1,5 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao;  public enum SelectedLoginMethod { -  EIDAS_LOGIN, MOBILE_PHONE_SIGNATURE_LOGIN, NO_OTHER_LOGIN, ADD_ME_AS_NEW +  EIDAS_LOGIN, MOBILE_PHONE_SIGNATURE_LOGIN, NO_OTHER_LOGIN, ADD_ME_AS_NEW, REQUESTING_NEW_ENTRY, STOP_MATCHING_PROCESS  } diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java index e8fb5b6b..dd46bfea 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java @@ -36,6 +36,7 @@ import javax.servlet.http.HttpServletResponse;  import org.jetbrains.annotations.NotNull;  import org.springframework.stereotype.Component; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; @@ -243,6 +244,7 @@ public class AlternativeSearchTask extends AbstractAuthServletTask {        throws WorkflowException, EaafStorageException {      MatchedPersonResult result = MatchedPersonResult.generateFormMatchingResult(          searchResult.getResult(), eidasData.getCitizenCountryCode()); +    MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.BY_EIDAS);      MatchingTaskUtils.storeFinalMatchingResult(pendingReq, result);      //remove intermediate matching-state diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java index c7843be5..563a66ba 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletResponse;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Component; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; @@ -91,7 +92,8 @@ public class CreateNewErnpEntryTask extends AbstractAuthServletTask {        }        // finish matching process, because new user-entry uniquly matches -      log.info("User successfully registerred into ERnP and matching tasks are finished "); +      log.info("User successfully registerred into ERnP and matching tasks are finished ");       +      MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.BY_NEW_ERNP_ENTRY);        MatchingTaskUtils.storeFinalMatchingResult(pendingReq,             MatchedPersonResult.generateFormMatchingResult(                resp.getPersonResult().get(0), simpleEidasData.getCitizenCountryCode())); diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java index a90c5929..94b29b8e 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java @@ -87,6 +87,11 @@ public class GenerateOtherLoginMethodGuiTask extends AbstractLocaleAuthServletTa          }               } +      // inject flag for matching-by-address allowed  +      config.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_UIOPTIONS, +          Constants.HTML_FORM_ENABLE_MATCHING_BY_ADDRESS_SEARCH,  +          String.valueOf(basicConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_MATCHING_BY_ADDRESS))); +                                // inject request to create a new ERnP entry        config.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_UIOPTIONS,            Constants.HTML_FORM_CREATE_NEW_ERNP_ENTRY,  diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java index 3a775837..8e6c7790 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java @@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletResponse;  import org.jetbrains.annotations.NotNull;  import org.springframework.stereotype.Component; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; @@ -123,7 +124,8 @@ public class InitialSearchTask extends AbstractAuthServletTask {          step6CountrySpecificSearch(executionContext, searchResult.getOperationStatus(), eidasData);        } else if (resultCount == 1) {         -        RegisterResult updatedResult = step3CheckRegisterUpdateNecessary(searchResult, eidasData);         +        RegisterResult updatedResult = step3CheckRegisterUpdateNecessary(searchResult, eidasData); +        MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.BY_PERSONALID);          foundMatchFinalizeTask(updatedResult, eidasData);        } else { @@ -151,6 +153,7 @@ public class InitialSearchTask extends AbstractAuthServletTask {      } else if (searchResult.getResultCount() == 1) {        log.trace("'step6CountrySpecificSearch' finds a person. Forward to 'step7aKittProcess' step ... ");        RegisterStatusResults updatedResult = registerSearchService.step7aKittProcess(searchResult, eidasData); +      MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.BY_COUNTRY_SPECIFIC);        foundMatchFinalizeTask(updatedResult.getResult(), eidasData);      } else { diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java index b8fe12fe..403c3355 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java @@ -41,6 +41,7 @@ import org.springframework.stereotype.Component;  import com.google.common.collect.Sets; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput; @@ -186,7 +187,8 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthS          // update register information          RegisterStatusResults updateResult = registerSearchService.step7aKittProcess(residencyResult, eidasData); -        // store updated result to re-used in CreateIdentityLink step, because there we need bPK and MDS +        // store updated result to re-used in CreateIdentityLink step, because there we need bPK and MDS         +        MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.BY_ADDRESS);          MatchingTaskUtils.storeFinalMatchingResult(pendingReq,              MatchedPersonResult.generateFormMatchingResult(                  updateResult.getResult(), eidasData.getCitizenCountryCode())); @@ -194,6 +196,7 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthS        } else {          log.warn("Suspect state FOUND. Matching by residence was neccessary but NO register-update are required!");          // no update required. Data can be used as it is. +        MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.BY_ADDRESS);          MatchingTaskUtils.storeFinalMatchingResult(pendingReq,              MatchedPersonResult.generateFormMatchingResult(                  residencyResult.getResult(), eidasData.getCitizenCountryCode())); diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java index b212d133..57790b01 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java @@ -47,6 +47,7 @@ import org.opensaml.saml.saml2.core.StatusCode;  import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;  import org.springframework.stereotype.Component; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; @@ -204,6 +205,7 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet          registerSearchService.step7aKittProcess(registerResult, eidasData);          // store search result to re-used in CreateIdentityLink step, because there we need bPK and MDS +        MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.BY_ID_AUSTRIA);          MatchingTaskUtils.storeFinalMatchingResult(pendingReq,              MatchedPersonResult.generateFormMatchingResult(registerResult.getResult(),                  eidasData.getCitizenCountryCode())); diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java index 184ad499..03414f9e 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java @@ -34,9 +34,13 @@ import org.springframework.stereotype.Component;  import com.google.common.collect.Sets; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SelectedLoginMethod; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;  import at.gv.egiz.eaaf.core.impl.idp.controller.tasks.AbstractLocaleAuthServletTask;  import lombok.extern.slf4j.Slf4j; @@ -73,15 +77,18 @@ public class ReceiveOtherLoginMethodGuiResponseTask extends AbstractLocaleAuthSe    @Override    public void executeWithLocale(ExecutionContext executionContext, HttpServletRequest request, -                                HttpServletResponse response) { +      HttpServletResponse response) throws TaskExecutionException {      try {        SelectedLoginMethod selection = SelectedLoginMethod.valueOf(extractUserSelection(request));        executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, false);        executionContext.put(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER, selection.name());        executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED); -      executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON);       -      transitionToNextTask(executionContext, selection); +      executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON); +      transitionToNextTask(executionContext, selection, request, response); +    } catch (TaskExecutionException e) { +      throw e; +            } catch (final Exception e) {        log.error("Parsing selected login method FAILED.", e);        executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); @@ -100,8 +107,15 @@ public class ReceiveOtherLoginMethodGuiResponseTask extends AbstractLocaleAuthSe      return null;    } -  private void transitionToNextTask(ExecutionContext executionContext, SelectedLoginMethod selection) { +  private void transitionToNextTask(ExecutionContext executionContext, SelectedLoginMethod selection, +      HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException {      switch (selection) { +      case STOP_MATCHING_PROCESS: +        log.info("Matching process WAS stopped by entity. Stopping auth. process ... "); +        MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.CANCELED_BY_USER); +        stopProcessFromUserDecision(executionContext, request, response); +        return; +              case EIDAS_LOGIN:          executionContext.put(Constants.TRANSITION_TO_GENERATE_EIDAS_LOGIN, true);          return; @@ -111,9 +125,22 @@ public class ReceiveOtherLoginMethodGuiResponseTask extends AbstractLocaleAuthSe          return;        case NO_OTHER_LOGIN: +        if (!authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_MATCHING_BY_ADDRESS)) { +          log.error("Matching by address was requested but it's disabled by configuration!"); +          throw new TaskExecutionException(pendingReq,  +              "Matching by address was requested but it's disabled by configuration!",  +              new EaafException("module.eidasauth.matching.98")); +           +        } +                  executionContext.put(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK, true);          return; +         +      case REQUESTING_NEW_ENTRY: +        executionContext.put(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK, true); +        return;         +                case ADD_ME_AS_NEW:          executionContext.put(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK, true);          return; diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/MatchingTaskUtils.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/MatchingTaskUtils.java index c8a1f190..c350cb05 100644 --- a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/MatchingTaskUtils.java +++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/MatchingTaskUtils.java @@ -15,6 +15,8 @@ import org.springframework.lang.NonNull;  import com.google.common.collect.ImmutableMap;  import com.google.common.collect.ImmutableSet; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants; +import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; @@ -27,7 +29,9 @@ import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;  import eu.eidas.auth.commons.attribute.AttributeDefinition;  import eu.eidas.auth.commons.attribute.AttributeValue;  import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress; +import lombok.extern.slf4j.Slf4j; +@Slf4j  public class MatchingTaskUtils {    /** @@ -105,7 +109,6 @@ public class MatchingTaskUtils {     * @param personInfos Person information after a successful match     * @throws EaafStorageException In case of data can not be add into session     */ -  @Nullable    public static void storeFinalMatchingResult(IRequest pendingReq, MatchedPersonResult personInfos)        throws EaafStorageException {      getAuthProcessDataWrapper(pendingReq).setGenericDataToSession( @@ -114,6 +117,23 @@ public class MatchingTaskUtils {    }    /** +   * Store matching result-state. +   *  +   * @param pendingReq Current pendingRequest +   * @param state Operation that results into a person match +   */ +  public static void setMatchingState(IRequest pendingReq, MatchingStates state) { +    try { +      pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_MATCHING_STATE, state); +       +    } catch (EaafStorageException e) { +      log.warn("Can NOT set matching-state for statistic logging.", e); +       +    }     +  } +   +   +  /**     * Get holder for authentication information for the current process.     *     * @param pendingReq Current pendingRequest diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml index dfa8622c..e57f9ca6 100644 --- a/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml +++ b/modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml @@ -45,6 +45,8 @@                    from="receiveOtherLoginMethodGuiResponseTask"     to="generateMobilePhoneSignatureRequestTask" />    <pd:Transition  conditionExpression="ctx['TASK_GenerateAustrianResidenceGuiTask']"                    from="receiveOtherLoginMethodGuiResponseTask"     to="generateAustrianResidenceGuiTask" /> +  <pd:Transition  conditionExpression="ctx['TASK_RequestingNewErnpEntryTask']" +                  from="receiveOtherLoginMethodGuiResponseTask"     to="generateOtherLoginMethodGuiTask" />    <pd:Transition  conditionExpression="ctx['TASK_CreateNewErnpEntryTask']"                    from="receiveOtherLoginMethodGuiResponseTask"     to="createNewErnpEntryTask" /> diff --git a/modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties b/modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties index 6d73c43a..dafa7ce3 100644 --- a/modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties +++ b/modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties @@ -30,5 +30,6 @@ module.eidasauth.matching.24=Matching be using Austrian Identity not possible. U  module.eidasauth.matching.25=Matching be using alternative eIDAS authentication not possible. Provide more or other data or use another method for matching.  module.eidasauth.matching.26=Matching be using alternative eIDAS authentication not possible, because Name or Country not matched. Provide more or other data or use another method for matching. +module.eidasauth.matching.98=Matching failed, because a method was selected that was not allowed.  module.eidasauth.matching.99=Matching failed, because of an unexpected processing error. Reason: {0} diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java index 496158fa..6d08a731 100644 --- a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java +++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java @@ -29,6 +29,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;  import com.fasterxml.jackson.databind.JsonNode;  import com.fasterxml.jackson.databind.json.JsonMapper; +import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SelectedLoginMethod;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.GenerateOtherLoginMethodGuiTask; @@ -53,6 +54,8 @@ public class GenerateOtherLoginMethodGuiTaskTest {    private static final String TEST_PATTER_REQ_PARAM =        "<input type=\"hidden\" name=\"loginSelection\" value=\"{0}\">"; +  @Autowired MsConnectorDummyConfigMap config; +      @Autowired    GenerateOtherLoginMethodGuiTask task; @@ -86,6 +89,9 @@ public class GenerateOtherLoginMethodGuiTaskTest {      executionContext = new ExecutionContextImpl(); +    config.putConfigValue("auth.eIDAS.matching.byaddress.enable", "false"); +     +          LocaleContextHolder.resetLocaleContext();    } @@ -172,6 +178,10 @@ public class GenerateOtherLoginMethodGuiTaskTest {      assertNotNull("createNewErnpEntry", json.get(Constants.HTML_FORM_CREATE_NEW_ERNP_ENTRY));      assertFalse("createNewErnpEntry", json.get(Constants.HTML_FORM_CREATE_NEW_ERNP_ENTRY).asBoolean()); +    assertNotNull("enableMatchingByAddressSearch", json.get(Constants.HTML_FORM_CREATE_NEW_ERNP_ENTRY)); +    assertFalse("enableMatchingByAddressSearch", json.get(Constants.HTML_FORM_CREATE_NEW_ERNP_ENTRY).asBoolean()); +     +          assertNotNull("pendingRequest not stored",           storage.getPendingRequest(pendingReq.getPendingRequestId())); @@ -199,10 +209,11 @@ public class GenerateOtherLoginMethodGuiTaskTest {    @Test    public void advancedMatchingFailedMsg() throws TaskExecutionException, UnsupportedEncodingException {      executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); - +    config.putConfigValue("auth.eIDAS.matching.byaddress.enable", "true"); +          task.execute(pendingReq, executionContext); -    String html = doBasicValidation(); +    String html = doBasicValidation(true);      Assert.assertFalse("Missing eIDAS infos",          html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM, SelectedLoginMethod.ADD_ME_AS_NEW)));      Assert.assertTrue("missing errorfield", @@ -218,7 +229,7 @@ public class GenerateOtherLoginMethodGuiTaskTest {      task.execute(pendingReq, executionContext); -    String html = doBasicValidation(); +    String html = doBasicValidation(false);      Assert.assertTrue("missing errorfield",          html.contains("<div id=\"matchingError\""));      Assert.assertTrue("missing errorfield", @@ -231,7 +242,7 @@ public class GenerateOtherLoginMethodGuiTaskTest {      task.execute(pendingReq, executionContext); -    doBasicValidation(); +    doBasicValidation(false);    } @@ -242,7 +253,7 @@ public class GenerateOtherLoginMethodGuiTaskTest {      task.execute(pendingReq, executionContext); -    doBasicValidation(); +    doBasicValidation(false);    } @@ -252,7 +263,7 @@ public class GenerateOtherLoginMethodGuiTaskTest {      task.execute(pendingReq, executionContext); -    doBasicValidation(); +    doBasicValidation(false);    } @@ -263,11 +274,11 @@ public class GenerateOtherLoginMethodGuiTaskTest {      task.execute(pendingReq, executionContext); -    doBasicValidation(); +    doBasicValidation(false);    } -  private String doBasicValidation() throws UnsupportedEncodingException { +  private String doBasicValidation(boolean addressSearchAllowed) throws UnsupportedEncodingException {      Assert.assertEquals("Wrong http StatusCode", 200, httpResp.getStatus());      Assert.assertEquals("Wrong http ContentType", "text/html;charset=UTF-8", httpResp.getContentType()); @@ -278,7 +289,8 @@ public class GenerateOtherLoginMethodGuiTaskTest {      Assert.assertTrue("Missing IDA Login",          html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM, SelectedLoginMethod.MOBILE_PHONE_SIGNATURE_LOGIN)));      Assert.assertTrue("Missing residence infos", -        html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM, SelectedLoginMethod.NO_OTHER_LOGIN))); +        html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM,  +            addressSearchAllowed ? SelectedLoginMethod.NO_OTHER_LOGIN : SelectedLoginMethod.REQUESTING_NEW_ENTRY)));      Assert.assertTrue("Missing eIDAS infos",          html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM, SelectedLoginMethod.EIDAS_LOGIN))); diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveOtherLoginMethodGuiResponseTaskTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveOtherLoginMethodGuiResponseTaskTest.java index 750a17ce..66867fce 100644 --- a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveOtherLoginMethodGuiResponseTaskTest.java +++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveOtherLoginMethodGuiResponseTaskTest.java @@ -4,6 +4,8 @@ import static org.junit.Assert.assertEquals;  import static org.junit.Assert.assertFalse;  import static org.junit.Assert.assertNotNull;  import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue;  import org.apache.commons.lang3.RandomStringUtils;  import org.junit.Before; @@ -21,9 +23,11 @@ import org.springframework.test.context.web.WebAppConfiguration;  import org.springframework.web.context.request.RequestContextHolder;  import org.springframework.web.context.request.ServletRequestAttributes; +import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SelectedLoginMethod;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveOtherLoginMethodGuiResponseTask; +import at.gv.egiz.eaaf.core.exceptions.EaafException;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;  import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;  import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; @@ -37,6 +41,8 @@ import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;  @WebAppConfiguration  public class ReceiveOtherLoginMethodGuiResponseTaskTest { +  @Autowired MsConnectorDummyConfigMap config; +      @Autowired    private ReceiveOtherLoginMethodGuiResponseTask task; @@ -68,10 +74,22 @@ public class ReceiveOtherLoginMethodGuiResponseTaskTest {      pendingReq.setAuthUrl("https://localhost/ms_connector");      pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); +    config.putConfigValue("auth.eIDAS.matching.byaddress.enable", "false"); +          LocaleContextHolder.resetLocaleContext();    }    @Test +  public void withStopMatchingSelection() throws TaskExecutionException { +httpReq.setParameter(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER,  SelectedLoginMethod.STOP_MATCHING_PROCESS.name()); +     +    task.execute(pendingReq, executionContext); +     +    assertTrue("stoppedByUser", pendingReq.isAbortedByUser()); +     +  } +   +  @Test    public void withMobileSignatureSelection() throws TaskExecutionException {      testTransition(SelectedLoginMethod.MOBILE_PHONE_SIGNATURE_LOGIN, Constants.TRANSITION_TO_GENERATE_MOBILE_PHONE_SIGNATURE_REQUEST_TASK);      assertEquals("return to selection", false, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); @@ -87,18 +105,40 @@ public class ReceiveOtherLoginMethodGuiResponseTaskTest {    @Test    public void withNoOtherLoginSelection() throws TaskExecutionException { +    config.putConfigValue("auth.eIDAS.matching.byaddress.enable", "true"); +          testTransition(SelectedLoginMethod.NO_OTHER_LOGIN, Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK);      assertEquals("return to selection", false, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK));    }    @Test +  public void withNoOtherLoginSelectionDisabled() throws TaskExecutionException {     +    httpReq.setParameter(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER,  SelectedLoginMethod.NO_OTHER_LOGIN.name()); +     +    TaskExecutionException error = assertThrows("wrong exception", TaskExecutionException.class, +        () -> task.execute(pendingReq, executionContext)); +     +    assertEquals("wrong errorCode", "module.eidasauth.matching.98",   +        ((EaafException) error.getOriginalException()).getErrorId()); +     +  } +   +  @Test    public void withAddMeAsNewSelection() throws TaskExecutionException {      testTransition(SelectedLoginMethod.ADD_ME_AS_NEW, Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK);      assertEquals("return to selection", false, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK));    } +  @Test +  public void withRequestingNewEntrySelection() throws TaskExecutionException { +    testTransition(SelectedLoginMethod.REQUESTING_NEW_ENTRY, Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK); +    assertEquals("return to selection", true, executionContext.get(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK)); +    assertEquals("return to selection", false, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +     +  } +      public void testTransition(SelectedLoginMethod loginMethod, String expectedTransition) throws TaskExecutionException {      httpReq.setParameter(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER, loginMethod.name());      executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); @@ -109,6 +149,8 @@ public class ReceiveOtherLoginMethodGuiResponseTaskTest {      assertFalse("wrong process-cancelled flag", executionContext.isProcessCancelled());      assertNotNull("no login-selection found", executionContext.get(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER));      assertEquals("Wrong login-selection found", loginMethod.name(), executionContext.get(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER)); +     +          assertEquals("Next task", true, executionContext.get(expectedTransition));      assertNull("find advancedMatchingError flag", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); diff --git a/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/AddressSearchResultTest.java b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/AddressSearchResultTest.java new file mode 100644 index 00000000..fef157db --- /dev/null +++ b/modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/utils/AddressSearchResultTest.java @@ -0,0 +1,56 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.utils; + +import static org.junit.Assert.assertArrayEquals; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.mockito.internal.util.collections.Sets; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput; + +@RunWith(BlockJUnit4ClassRunner.class) +public class AddressSearchResultTest { +   +  @Test +  public void checkNumbers() { +     +    Set<AdresssucheOutput> result = Sets.newSet( +        buildRandom("2"), +        buildRandom("3"), +        buildRandom("1"), +        buildRandom("10"), +        buildRandom(null), +        buildRandom("10-12"), +        buildRandom("15") +        ); +     +    final List<String> sorted = result.stream().sorted().limit(30) +        .map(el -> el.getNumber())         +        .collect(Collectors.toList()); + +     +    assertArrayEquals("wrong order",  +        new Object[]{null, "1", "2", "3", "10", "15", "10-12"},         +        sorted.toArray()); +     +     +             +     +  } + +  private AdresssucheOutput buildRandom(String number) { +    return AdresssucheOutput.builder() +        .municipality("aaaaaaaa") +        .postleitzahl("8080") +        .street("bbbbb") +        .number(number) +        .village("cccccc") +        .build(); +   } + +} | 
