diff options
| author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2022-03-03 15:27:30 +0000 | 
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2022-03-03 15:27:30 +0000 | 
| commit | d8247d4de494c176f78658fa2c0a38ac9ceab0aa (patch) | |
| tree | d0b6bf2293b6e82282bfbab595e0b4d39fdb0428 /eidas_modules/authmodule-eIDAS-v2/src | |
| parent | b81ef7a782278cb941d3b424ccbe1ccc976c54f3 (diff) | |
| parent | c3bba97c9093eca911f6edd9cbb9742d5f32583c (diff) | |
| download | National_eIDAS_Gateway-d8247d4de494c176f78658fa2c0a38ac9ceab0aa.tar.gz National_eIDAS_Gateway-d8247d4de494c176f78658fa2c0a38ac9ceab0aa.tar.bz2 National_eIDAS_Gateway-d8247d4de494c176f78658fa2c0a38ac9ceab0aa.zip | |
Merge branch 'feature/matching_ernp_client' into 'feature/matching_base'
refactor(ernp): update openAPI specification from BM.I to use...
See merge request egiz/eidas_at_proxy!16
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src')
70 files changed, 8065 insertions, 848 deletions
| diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java index bfb82474..272d79c4 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java @@ -100,6 +100,31 @@ public class Constants {    public static final String FORWARD_METHOD_POST = "POST";    public static final String FORWARD_METHOD_GET = "GET"; +   +  // Common SSL client configuration  +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT = CONIG_PROPS_EIDAS_PREFIX + ".client.common"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PATH = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.keyStore.path"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PASSWORD = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.keyStore.password"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_TYPE = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.keyStore.type"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_NAME = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.keyStore.name"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYS_ALIAS = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.key.alias"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEY_PASSWORD = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.key.password"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_PATH = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.trustStore.path"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_PASSWORD = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.trustStore.password"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_TYPE = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.trustStore.type"; +  public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_NAME = CONIG_PROPS_EIDAS_COMMON_CLIENT +      + ".ssl.trustStore.name"; +   +        // ZMR Client configuration properties    public static final String CONIG_PROPS_EIDAS_ZMRCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".zmrclient";    public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_ENDPOINT = CONIG_PROPS_EIDAS_ZMRCLIENT @@ -110,6 +135,12 @@ public class Constants {        + ".timeout.connection";    public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_TIMEOUT_RESPONSE = CONIG_PROPS_EIDAS_ZMRCLIENT        + ".timeout.response"; +  public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR = CONIG_PROPS_EIDAS_ZMRCLIENT +      + ".req.organisation.behoerdennr"; +  public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_CODE = CONIG_PROPS_EIDAS_ZMRCLIENT +      + ".req.update.reason.code"; +  public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_TEXT = CONIG_PROPS_EIDAS_ZMRCLIENT +      + ".req.update.reason.text";    public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_PATH = CONIG_PROPS_EIDAS_ZMRCLIENT        + ".ssl.keyStore.path";    public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_PASSWORD = CONIG_PROPS_EIDAS_ZMRCLIENT @@ -130,15 +161,19 @@ public class Constants {        + ".ssl.trustStore.type";    public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_NAME = CONIG_PROPS_EIDAS_ZMRCLIENT        + ".ssl.trustStore.name"; - -  public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR = CONIG_PROPS_EIDAS_ZMRCLIENT +   +  // ErnP Client configuration properties +  public static final String CONIG_PROPS_EIDAS_ERNPCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".ernpclient"; +  public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_ENDPOINT = CONIG_PROPS_EIDAS_ERNPCLIENT +      + ".endpoint"; +  public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_TIMEOUT_CONNECTION = CONIG_PROPS_EIDAS_ERNPCLIENT +      + ".timeout.connection"; +  public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_TIMEOUT_RESPONSE = CONIG_PROPS_EIDAS_ERNPCLIENT +      + ".timeout.response"; +  public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_REQ_ORGANIZATION_NR = CONIG_PROPS_EIDAS_ERNPCLIENT        + ".req.organisation.behoerdennr"; -  public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_CODE = CONIG_PROPS_EIDAS_ZMRCLIENT -      + ".req.update.reason.code"; -  public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_TEXT = CONIG_PROPS_EIDAS_ZMRCLIENT -      + ".req.update.reason.text"; - - +   +      // SZR Client configuration properties    public static final String CONIG_PROPS_EIDAS_SZRCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".szrclient";    public static final String CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE = CONIG_PROPS_EIDAS_SZRCLIENT @@ -233,7 +268,13 @@ public class Constants {    public static final String eIDAS_ATTRURN_PREFIX_NATURAL = eIDAS_ATTRURN_PREFIX + "naturalperson/";    public static final String eIDAS_ATTRURN_PERSONALIDENTIFIER = -      eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_PERSONALIDENTIFIER; +      eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_PERSONALIDENTIFIER;   +  public static final String eIDAS_ATTRURN_CURRENTGIVENNAME = +      eIDAS_ATTRURN_PREFIX_NATURAL + "CurrentGivenName"; +  public static final String eIDAS_ATTRURN_CURRENTFAMILYNAME = +      eIDAS_ATTRURN_PREFIX_NATURAL + "CurrentFamilyName"; +  public static final String eIDAS_ATTRURN_DATEOFBIRTH = +      eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_DATEOFBIRTH;      public static final String eIDAS_ATTRURN_PLACEOFBIRTH =        eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_PLACEOFBIRTH;    public static final String eIDAS_ATTRURN_BIRTHNAME = @@ -255,8 +296,10 @@ public class Constants {    public static final String SZR_SCHEMA_LOCATIONS =        "urn:SZRServices" + " " + "/szr_client/szr.xsd"; -  // Default values for SZR communication +  // Default values for SZR / ZMR / ERnP communication    public static final String SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE = "ELEKTR_DOKUMENT"; +  public static final String CLIENT_INFO = "eIDAS MS-Connector v{0}"; +      // AuthBlock    public static final String SZR_AUTHBLOCK = "authData_AUTHBLOCK"; @@ -277,10 +320,14 @@ public class Constants {    // UI options    public static final String HTML_FORM_ADVANCED_MATCHING_FAILED = "advancedMatchingFailed"; - +  public static final String HTML_FORM_ADVANCED_MATCHING_FAILED_REASON =  +      HTML_FORM_ADVANCED_MATCHING_FAILED + "Reason"; +      // ProcessEngine context    public static final String CONTEXT_FLAG_ADVANCED_MATCHING_FAILED = HTML_FORM_ADVANCED_MATCHING_FAILED; +  public static final String CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON =  +      HTML_FORM_ADVANCED_MATCHING_FAILED_REASON;    /**     * {@link at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateNewErnpEntryTask}. diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java new file mode 100644 index 00000000..4c4e3d87 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -0,0 +1,857 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp; + +import java.io.IOException; +import java.text.MessageFormat; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; +import javax.annotation.PostConstruct; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.HttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +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.dao.SimpleEidasData.SimpleEidasDataBuilder; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.api.DefaultApi; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.invoker.ApiClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Aendern; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AendernResponse; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Anlegen; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AnlegenResponse; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Eidas; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PartialDate; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Person; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAendern; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAnlegen; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonSuchen; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Personendaten; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonendatenErgebnis; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchEidas; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchdaten; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchenResponse; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchoptionen; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchoptionen.HistorischEnum; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ErnpRestCommunicationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.VersionHolder; +import at.gv.bmi.namespace.zmr_su.base._20040201_.ServiceFault; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.EidasSuchdatenType; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.http.HttpClientConfiguration; +import at.gv.egiz.eaaf.core.impl.http.HttpClientConfiguration.ClientAuthMode; +import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Implements an ERnP client that uses REST API for communication. + * + * @author tlenz + * + */ +@Slf4j +public class ErnpRestClient implements IErnpClient { + +  private static final String ERROR_MATCHING_11 = "module.eidasauth.matching.11"; +  //private static final String ERROR_MATCHING_12 = "module.eidasauth.matching.12"; +  private static final String ERROR_MATCHING_99 = "module.eidasauth.matching.99"; + +  private static final String LOGMSG_MISSING_CONFIG = "Missing configuration with key: {0}"; +  private static final String LOGMSG_ERNP_ERROR = +      "Receive an error from ERnP during '{}' operation with msg: {}"; +  private static final String LOGMSG_ERNP_RESP_PROCESS = +      "Proces ERnP response during '{}' operation failes with msg: {}"; + +  //private static final String LOGMSG_ERNP_REST_ERROR = +  //    "ERnP anwser for transaction: {0} with code: {1} and message: {2}"; + +  private static final String PROCESS_SEARCH_PERSONAL_IDENTIFIER = +      "Searching " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER; +  private static final String PROCESS_SEARCH_MDS_ONLY = "Searching with MDS only"; +  private static final String PROCESS_SEARCH_COUNTRY_SPECIFIC = "Searching {0} specific"; + +  private static final String PROCESS_KITT_GENERAL = "KITT general-processing"; +  private static final String PROCESS_KITT_IDENITIES_GET = "KITT get-latest-version"; +  private static final String PROCESS_KITT_IDENITIES_UPDATE = "KITT update dataset"; +  private static final String PROCESS_ADD_IDENITY = "Add new person"; +   +  private static final String FRIENDLYNAME_HTTP_CLIENT = "ERnP Client"; + +  // HTTP header-names from ERnP response  +  private static final String ERNP_RESPONSE_HEADER_SERVER_ID = "Server-Request-Id"; +   +   +  @Autowired +  IConfiguration basicConfig; +  @Autowired +  EaafKeyStoreFactory keyStoreFactory; +  @Autowired +  IHttpClientFactory httpClientFactory; +  @Autowired +  VersionHolder versionHolder; + +  private DefaultApi ernpClient; + +  @Override +  public ErnpRegisterResult searchWithPersonIdentifier(String personIdentifier, String citizenCountryCode) +      throws EidasSAuthenticationException { +    try { +      // build generic request metadata +      final GenericRequestParams generic = buildGenericRequestParameters("stepId"); + +      // build search request +      final SuchEidas eidasInfos = new SuchEidas(); +      eidasInfos.setArt(Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER); +      eidasInfos.setWert(personIdentifier); +      eidasInfos.setStaatscode2(citizenCountryCode); + +      final PersonSuchen personSuchen = new PersonSuchen(); +      personSuchen.setSuchoptionen(generateSearchParameters()); +      personSuchen.setBegruendung(PROCESS_SEARCH_PERSONAL_IDENTIFIER); +      final Suchdaten searchInfos = new Suchdaten(); +      searchInfos.setEidas(Arrays.asList(eidasInfos)); +      personSuchen.setSuchdaten(searchInfos); + +      // request ERnP +      log.trace("Requesting ERnP for '{}' operation", PROCESS_SEARCH_PERSONAL_IDENTIFIER); +      final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, +          generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + +      // parse ZMR response +      return processErnpResponse(resp, citizenCountryCode, true, PROCESS_SEARCH_PERSONAL_IDENTIFIER); + +    } catch (RestClientException e) { +      log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_PERSONAL_IDENTIFIER, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); +       +    } catch (final EidasSAuthenticationException e) { +      throw e; + +    } catch (final Exception e) { +      log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_PERSONAL_IDENTIFIER, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); +    } + +  } + +  @Override +  public ErnpRegisterResult searchWithMds(String givenName, String familyName, String dateOfBirth, +      String citizenCountryCode) throws EidasSAuthenticationException { +    try { +      // build generic request metadata +      final GenericRequestParams generic = buildGenericRequestParameters("stepMDS"); + +      // build search request +      final Suchdaten searchInfos = new Suchdaten(); +      searchInfos.setFamilienname(familyName); +      searchInfos.setVorname(givenName); +      searchInfos.setGeburtsdatum(buildErnpBirthday(dateOfBirth)); +             +      final PersonSuchen personSuchen = new PersonSuchen(); +      personSuchen.setSuchoptionen(generateSearchParameters()); +      personSuchen.setBegruendung(PROCESS_SEARCH_MDS_ONLY);            +      personSuchen.setSuchdaten(searchInfos); + +      // request ERnP +      log.trace("Requesting ERnP for '{}' operation", PROCESS_SEARCH_MDS_ONLY); +      final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, +          generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + +      // parse ZMR response +      return processErnpResponse(resp, citizenCountryCode, false, PROCESS_SEARCH_MDS_ONLY); + +    } catch (RestClientException e) { +      log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_MDS_ONLY, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); +       +    } catch (final EidasSAuthenticationException e) { +      throw e; + +    } catch (final Exception e) { +      log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_MDS_ONLY, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); +    } +  } +   +  @Override +  public ErnpRegisterResult searchCountrySpecific(PersonSuchenRequest personSearchDao, +      String citizenCountryCode) throws EidasSAuthenticationException { +    String countrySearchMsg = MessageFormat.format(PROCESS_SEARCH_COUNTRY_SPECIFIC, citizenCountryCode); +     +    try {             +      // build generic request metadata +      final GenericRequestParams generic = buildGenericRequestParameters("stepCC"); + +      // build search request             +      final PersonSuchen personSuchen = new PersonSuchen(); +      personSuchen.setSuchoptionen(generateSearchParameters()); +      personSuchen.setBegruendung(countrySearchMsg);            +      personSuchen.setSuchdaten(mapCountrySpecificSearchData(personSearchDao)); + +      // request ERnP +      log.trace("Requesting ERnP for '{}' operation", countrySearchMsg); +      final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, +          generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + +      // parse ZMR response +      return processErnpResponse(resp, citizenCountryCode, true, countrySearchMsg); + +    } catch (RestClientException e) { +      log.warn(LOGMSG_ERNP_ERROR, countrySearchMsg, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); +       +    } catch (final EidasSAuthenticationException e) { +      throw e; + +    } catch (final Exception e) { +      log.warn(LOGMSG_ERNP_RESP_PROCESS, countrySearchMsg, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); +       +    } +  } + +  @Override +  public ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) +      throws EidasSAuthenticationException { +    try { +      //search person with register result, because update needs information from search response +      Person ernpPersonToKitt = searchPersonForUpdate(registerResult); +             +      // select elements that have to be updated +      Collection<? extends Eidas> eidasDocumentToAdd =  +          selectEidasDocumentsToAdd(ernpPersonToKitt, eidData);       +      SimpleEidasData mdsToUpdate = selectMdsInformationToUpdate(ernpPersonToKitt, eidData);  +       +      if (eidasDocumentToAdd.isEmpty() && mdsToUpdate == null) { +        log.info("Find no eIDAS document or MDS for update during: {}. Nothing todo on ERnP side",  +            PROCESS_KITT_GENERAL); +        return new ErnpRegisterResult(Arrays.asList(registerResult)); +         +      } else { +        log.info("Find #{} eIDAS documents for update during: {}", eidasDocumentToAdd.size(), PROCESS_KITT_GENERAL); +         +        // update entry based on selected update info's and results from search response  +        return updatePersonInErnp(ernpPersonToKitt, eidasDocumentToAdd, mdsToUpdate, eidData.getCitizenCountryCode());   +         +      } + +    } catch (RestClientException e) { +      log.warn(LOGMSG_ERNP_ERROR, PROCESS_KITT_GENERAL, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); +       +    } catch (final EidasSAuthenticationException e) { +      throw e; + +    } catch (final Exception e) { +      log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_KITT_GENERAL, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); +       +    }     +  } + +  @Override +  public ErnpRegisterResult add(SimpleEidasData eidData) throws EidasSAuthenticationException { +    try { +      // build generic request metadata +      final GenericRequestParams generic = buildGenericRequestParameters("stepNew"); +       +      // build update request +      PersonAnlegen ernpReq = new PersonAnlegen(); +      ernpReq.setBegruendung(PROCESS_ADD_IDENITY); +           +      // inject person data +      Personendaten person = new Personendaten(); +      person.setFamilienname(eidData.getFamilyName()); +      person.setVorname(eidData.getGivenName()); +      person.setGeburtsdatum(buildErnpBirthday(eidData.getDateOfBirth()));        +      ernpReq.setPersonendaten(person); +       +      buildNewEidasDocumens(ernpReq, eidData); +              +      // request ERnP +      log.trace("Requesting ERnP for '{}' operation", PROCESS_ADD_IDENITY);        +      AnlegenResponse ernpResp = ernpClient.anlegen(generic.getClientBehkz(), generic.clientName, +          generic.getClientRequestTime(), generic.getClientRequestId(), ernpReq);         +      log.trace("Receive response from ERnP for '{}' operation", PROCESS_ADD_IDENITY); +       +      return  new ErnpRegisterResult(Arrays.asList( +          mapErnpResponseToRegisterResult(ernpResp.getPerson(), eidData.getCitizenCountryCode())));     +     +    } catch (RestClientException e) { +      log.warn(LOGMSG_ERNP_ERROR, PROCESS_ADD_IDENITY, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); +       +    } catch (final Exception e) { +      log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_ADD_IDENITY, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); +       +    }     +  } +   +  @Override +  public ErnpRegisterResult searchWithResidenceData(String givenName, String familyName, String dateOfBirth, +      String zipcode, String city, String street) {     +    log.warn("Matching with residence information is prohibited by design! This requests will be ignored"); +    return new ErnpRegisterResult(Collections.emptyList()); +     +  } +   +  @PostConstruct +  private void initialize() throws EaafException { +    // validate additional Ernp communication parameters +    valdiateAdditionalConfigParameters(); + +    // set-up the Ernp client +    final ApiClient baseClient = new ApiClient(buildRestClient()); +    baseClient.setBasePath(basicConfig.getBasicConfiguration( +        Constants.CONIG_PROPS_EIDAS_ERNPCLIENT_ENDPOINT)); +    ernpClient = new DefaultApi(baseClient); + +  } + +  private void valdiateAdditionalConfigParameters() { +    checkConfigurationValue(Constants.CONIG_PROPS_EIDAS_ERNPCLIENT_ENDPOINT); +    checkConfigurationValue(Constants.CONIG_PROPS_EIDAS_ERNPCLIENT_REQ_ORGANIZATION_NR); + +  } + +  private void checkConfigurationValue(String key) { +    if (StringUtils.isEmpty(basicConfig.getBasicConfiguration(key))) { +      throw new RuntimeException(MessageFormat.format(LOGMSG_MISSING_CONFIG, key)); + +    } +  } + +  private Suchoptionen generateSearchParameters() { +    final Suchoptionen options = new Suchoptionen(); +    options.setZmr(false); +    options.setHistorisch(HistorischEnum.AKTUELLUNDHISTORISCH); +    options.setSucheMitNamensteilen(false); +    options.setSuchwizard(false); +    return options; + +  } + +  @Nonnull +  private ErnpRegisterResult processErnpResponse(SuchenResponse resp, @Nonnull String citizenCountryCode, +      boolean forceSinglePersonMatch, @Nonnull String processStepFiendlyname) +      throws EaafAuthenticationException { +    if (resp.getPerson() == null +        || resp.getPerson().isEmpty()) { +      log.debug("ERnP result contains NO 'Person' or 'Person' is empty"); +      return new ErnpRegisterResult(Collections.emptyList()); + +    } else { +      log.debug("Get #{} person results from '{}' operation", +          resp.getPerson().size(), processStepFiendlyname); + +      if (forceSinglePersonMatch) { +        return new ErnpRegisterResult(processSearchPersonResponseSingleResult( +            resp.getPerson(), citizenCountryCode, processStepFiendlyname)); + +      } else { +        return new ErnpRegisterResult(processSearchPersonResponse( +            resp.getPerson(), citizenCountryCode)); + +      } +    } +  } + +  @Nonnull +  private List<RegisterResult> processSearchPersonResponse( +      @Nonnull List<Person> list, +      @Nonnull String citizenCountryCode) throws EaafAuthenticationException { +    return list.stream() +        .map(el -> mapErnpResponseToRegisterResult(el, citizenCountryCode)) +        .filter(Objects::nonNull) +        .collect(Collectors.toList()); + +  } + +  @NonNull +  private List<RegisterResult> processSearchPersonResponseSingleResult( +      @Nonnull List<Person> persons, +      @Nonnull String citizenCountryCode, String processStepFiendlyname) throws EaafAuthenticationException { +    if (persons.size() > 1) { +      log.error("Find more-than-one ERnP entry with search criteria that has to be unique"); +      throw new WorkflowException(processStepFiendlyname, +          "Find more-than-one ERnP entry with search criteria that has to be unique", true); + +    } else { +      return Arrays.asList(mapErnpResponseToRegisterResult(persons.get(0), citizenCountryCode)); + +    } +  } + +  @Nonnull +  private RegisterResult mapErnpResponseToRegisterResult(@Nonnull Person person, +      @Nonnull String citizenCountryCode) { +    // build result +    return RegisterResult.builder() +        .pseudonym(selectAllEidasDocument(person, citizenCountryCode, +            Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER)) +        .familyName(person.getPersonendaten().getFamilienname()) +        .givenName(person.getPersonendaten().getVorname()) +        .dateOfBirth(getTextualBirthday(person.getPersonendaten().getGeburtsdatum())) +        .bpk(person.getPersonendaten().getBpkZp()) +        .placeOfBirth(selectSingleEidasDocument(person, citizenCountryCode, +            Constants.eIDAS_ATTRURN_PLACEOFBIRTH)) +        .birthName(selectSingleEidasDocument(person, citizenCountryCode, +            Constants.eIDAS_ATTRURN_BIRTHNAME)) +        .build(); + +  } + +  private Suchdaten mapCountrySpecificSearchData(PersonSuchenRequest personSearchDao) {             +    final Suchdaten searchInfos = new Suchdaten(); +    searchInfos.setFamilienname(personSearchDao.getNatuerlichePerson().getPersonenName().getFamilienname());       +    searchInfos.setVorname(personSearchDao.getNatuerlichePerson().getPersonenName().getVorname()); +    searchInfos.setGeburtsdatum(buildErnpBirthday(personSearchDao.getNatuerlichePerson().getGeburtsdatum()));     +     +    // map all eIDAS documents into ERnP format +    searchInfos.setEidas(personSearchDao.getEidasSuchdaten().stream() +        .map(el -> buildErnpEidasDocument(el)) +        .collect(Collectors.toList())); +            +    return searchInfos; +     +  } +   +  private ErnpRegisterResult updatePersonInErnp(Person ernpPersonToKitt, +      Collection<? extends Eidas> eidasDocumentToAdd, SimpleEidasData mdsToUpdate, String citizenCountryCode)  +          throws ServiceFault { +    // build generic request metadata +    final GenericRequestParams generic = buildGenericRequestParameters("stepKittUpdate"); +     +    // build update request +    PersonAendern ernpReq = new PersonAendern(); +    ernpReq.setBegruendung(PROCESS_KITT_IDENITIES_UPDATE); +     +    // set reference elements for person update +    ernpReq.setEntityId(ernpPersonToKitt.getEntityId()); +    ernpReq.setVersion(ernpPersonToKitt.getVersion());     +     +    // add new eIDAS attributes +    if (!eidasDocumentToAdd.isEmpty()) { +      log.debug("Find eIDAS Documents to update. Injection update entries into ERnP request ... "); +      ernpReq.setAnlegen(new Anlegen());       +      eidasDocumentToAdd.stream().forEach(el -> ernpReq.getAnlegen().addEidasItem(el)); +       +    } +     +    // update MDS if required +    if (mdsToUpdate != null) { +      log.debug("Find MDS to update. Injection update entries into ERnP request ... "); +      ernpReq.setAendern(generateMdsChangeRequest(ernpPersonToKitt, mdsToUpdate)); +             +    } +     +    // request ERnP +    log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE);        +    AendernResponse ernpResp = ernpClient.aendern(generic.getClientBehkz(), generic.clientName, +        generic.getClientRequestTime(), generic.getClientRequestId(), ernpReq);         +    log.trace("Receive response from ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); +     +    return  new ErnpRegisterResult(Arrays.asList( +        mapErnpResponseToRegisterResult(ernpResp.getPerson(), citizenCountryCode)));     +     +  } +   +  private Collection<? extends Eidas> selectEidasDocumentsToAdd( +      Person ernpPersonToKitt, SimpleEidasData eidData) { + +    //TODO: maybe we should re-factor SimpleEidasData to a generic data-model to facilitate arbitrary eIDAS attributes   +    Set<Eidas> result = new HashSet<>();    +    addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(),  +        Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER, eidData.getPseudonym(), true);     +    addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(),  +        Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth(), false); +    addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(),  +        Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName(), false); +         +    return result; +     +  } +   +  private void addEidasDocumentIfNotAvailable(Set<Eidas> result, +      Person ernpPersonToKitt, String citizenCountryCode,  +      String attrName, String attrValue, boolean allowMoreThanOneEntry) { + +    if (StringUtils.isEmpty(attrValue)) { +      log.trace("No eIDAS document: {}. Nothing todo for KITT process ... ", attrName); +      return; +       +    } +     +    // check if eIDAS attribute is already includes an eIDAS-Document  +    boolean alreadyExist = ernpPersonToKitt.getEidas().stream() +        .filter(el -> el.getWert().equals(attrValue)  +            && el.getArt().equals(attrName) +            && el.getStaatscode2().equals(citizenCountryCode))      +        .findAny() +        .isPresent(); +     +    if (!alreadyExist) {     +      // check eIDAS documents already contains a document with this pair of country-code and attribute-name +      Optional<Eidas> oneDocWithNameExists = ernpPersonToKitt.getEidas().stream() +          .filter(el -> el.getStaatscode2().equals(citizenCountryCode)  +              && el.getArt().equals(attrName)) +          .findAny(); +       +      if (!allowMoreThanOneEntry && oneDocWithNameExists.isPresent() +          && !oneDocWithNameExists.get().getWert().equals(attrValue)) {                   +        log.warn("eIDAS document: {} already exists for country: {} but attribute-value does not match. " +            + "Skip update process because no multi-value allowed for this ... ", +            attrName, citizenCountryCode);   +           +      } else { +         +        Eidas eidasDocToAdd = new Eidas(); +        eidasDocToAdd.setStaatscode2(citizenCountryCode); +        eidasDocToAdd.setArt(attrName); +        eidasDocToAdd.setWert(attrValue);         +        log.info("Add eIDAS document: {} for country: {} to ERnP person", attrName, citizenCountryCode); +        result.add(eidasDocToAdd); +           +      } +               +    } else { +      log.debug("eIDAS document: {} already exists for country: {}. Skip update process for this ... ", +          attrName, citizenCountryCode);   +       +    } +  } +   +  private Person searchPersonForUpdate(RegisterResult registerResult) throws WorkflowException { +    // build generic request metadata +    final GenericRequestParams generic = buildGenericRequestParameters("stepKittSearch"); + +    // build search request +    final Suchdaten searchInfos = new Suchdaten(); +    searchInfos.setBpkZp(registerResult.getBpk()); +    searchInfos.setFamilienname(registerResult.getFamilyName()); +    searchInfos.setVorname(registerResult.getGivenName()); +    searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth()));               +     +    final PersonSuchen personSuchen = new PersonSuchen(); +    personSuchen.setSuchoptionen(generateSearchParameters()); +    personSuchen.setBegruendung(PROCESS_KITT_IDENITIES_GET);            +    personSuchen.setSuchdaten(searchInfos); + +    // request ERnP +    log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_GET); +    final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, +        generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + +    // perform shot validation of ERnP response +    if (resp.getPerson() == null || resp.getPerson().size() != 1) { +      log.error("ERnP result contains NO 'Person' or 'Person' is empty"); +      throw new WorkflowException(PROCESS_KITT_IDENITIES_GET,  +          "Find NO data-set with already matchted eID during ERnP KITT process"); +       +    } else { +      log.debug("Find person for '{}' operation", PROCESS_KITT_IDENITIES_GET); +      return resp.getPerson().get(0);      +       +    }         +  } +   +  private void buildNewEidasDocumens(PersonAnlegen ernpReq, SimpleEidasData eidData) { +    ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(),  +        Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER, eidData.getPseudonym())); +     +    if (StringUtils.isNotEmpty(eidData.getPlaceOfBirth())) { +      ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(), +          Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth())); +         +    } +         +    if (StringUtils.isNotEmpty(eidData.getBirthName())) { +      ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(),  +          Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName())); +       +    }         +  } + +  private Eidas buildNewEidasDocument(String citizenCountryCode, String eidasAttrName, +      String eidasAddrValue) { +    Eidas el = new Eidas(); +    el.setArt(eidasAttrName); +    el.setWert(eidasAddrValue); +    el.setStaatscode2(citizenCountryCode); +    return el; +  } +     +  private SimpleEidasData selectMdsInformationToUpdate(Person ernpPersonToKitt, SimpleEidasData eidData) {     +    PersonendatenErgebnis person = ernpPersonToKitt.getPersonendaten(); +    SimpleEidasDataBuilder builder = SimpleEidasData.builder() +        .givenName(eidData.getGivenName()) +        .familyName(eidData.getFamilyName()) +        .dateOfBirth(eidData.getDateOfBirth()); +     +    boolean findMatch = person.getVorname().equals(eidData.getGivenName()) +        && person.getFamilienname().equals(eidData.getFamilyName()) +        && getTextualBirthday(person.getGeburtsdatum()).equals(eidData.getDateOfBirth());     +    return findMatch ? null : builder.build(); +     +  } +   +  private Aendern generateMdsChangeRequest(Person ernpPersonToKitt, SimpleEidasData mdsToUpdate) { +    Aendern el = new Aendern();     +    Personendaten person = new Personendaten(); +    person.setEntityId(ernpPersonToKitt.getPersonendaten().getEntityId()); +    el.setPersonendaten(person); +    person.setFamilienname(mdsToUpdate.getFamilyName()); +    person.setVorname(mdsToUpdate.getGivenName()); +    person.setGeburtsdatum(buildErnpBirthday(mdsToUpdate.getDateOfBirth()));                +    return el; +     +  } +   +  /** +   * Map an AT specific Date String 'yyyy-MM-dd' to ERnP birthday representation. +   *  +   * <p> +   *  <b>Info:</b> {@link LocalDate} can not be used, because '1940-00-00' is also +   * a valid birthday. +   * </p> +   *  +   * @param dateOfBirth in 'yyyy-MM-dd' format +   * @return ERnP birthday representation +   */ +  private PartialDate buildErnpBirthday(String dateOfBirth) {         +    String[] elements = dateOfBirth.split("-"); +    Assert.isTrue(elements.length == 3, "Find invalid dateOfBirth element: " + dateOfBirth); +     +    PartialDate result = new PartialDate();  +    result.setJahr(Integer.valueOf(elements[0])); +    result.setMonat(Integer.valueOf(elements[1])); +    result.setTag(Integer.valueOf(elements[2]));         +    return result; +     +  } + +  /** +   * Map eIDAS search-data from ZMR model into ERnP model. +   *  +   * @param daten eIDAS document as ZMR model +   * @return the same eIDAS document as an ERnP model +   */ +  private SuchEidas buildErnpEidasDocument(EidasSuchdatenType daten) {   +    return new SuchEidas() +        .art(daten.getEidasArt()) +        .wert(daten.getEidasWert()) +        .staatscode2(daten.getStaatscode2());    +  } +   +   +  /** +   * Build AT specific Date String 'yyyy-MM-dd' from ERnP birthday representation. +   * +   * <p> +   *  <b>Info:</b> {@link LocalDate} can not be used, because '1940-00-00' is also +   * a valid birthday on ERnP site. +   * </p> +   * +   * @param geburtsdatum ERnP birthday representation +   * @return birthday in 'yyyy-MM-dd' format +   */ +  private String getTextualBirthday(PartialDate geburtsdatum) { +    return MessageFormat.format("{0}-{1}-{2}", +        String.valueOf(geburtsdatum.getJahr()), +        String.format("%02d", geburtsdatum.getMonat()), +        String.format("%02d", geburtsdatum.getTag())); + +  } + +   +  /** +   * Get all eIDAS document with the specified country code and document type. +   * +   * @param person                         Person information from ERnP +   * @param citizenCountryCode             Country code of the eIDAS attribute +   * @param eidasAttrurnPersonalidentifier eIDAS attribute identifier +   * @return {@link List} of eIDAS attribute values or an empty list if's not +   *         found +   */ +  @NonNull +  private List<String> selectAllEidasDocument(Person person, String citizenCountryCode, +      String eidasAttrurnPersonalidentifier) { +    if (person.getEidas() != null) { +      return person.getEidas().stream() +          .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) +              && el.getStaatscode2().equals(citizenCountryCode)) +          .map(el -> el.getWert()) +          .collect(Collectors.toList()); + +    } else { +      return Collections.emptyList(); + +    } + +  } + +  /** +   * Get the first eIDAS document with the specified country code and document +   * type. +   * +   * @param person                         Person information from ERnP +   * @param citizenCountryCode             Country code of the eIDAS attribute +   * @param eidasAttrurnPersonalidentifier eIDAS attribute identifier +   * @return Value of this eIDAS attribute or <code>null</code> if's not found +   */ +  @Nullable +  private String selectSingleEidasDocument(Person person, String citizenCountryCode, +      String eidasAttrurnPersonalidentifier) { +    if (person.getEidas() != null) { +      return person.getEidas().stream() +          .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) +              && el.getStaatscode2().equals(citizenCountryCode)) +          .findFirst() +          .map(el -> el.getWert()) +          .orElse(null); + +    } else { +      return null; + +    } +  } + +  private RestTemplate buildRestClient() throws EaafException { +    log.debug("Building REST-Client for ERnP communication ... "); +    final HttpClient httpClient = httpClientFactory.getHttpClient(buildHttpClientConfiguration()); +    final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); +    final RestTemplate springClient = new RestTemplate(requestFactory); +    springClient.setErrorHandler(buildErrorHandler()); +    springClient.getMessageConverters().add(0, buildCustomJacksonObjectMapper()); +    return springClient; + +  } + +  private HttpMessageConverter<?> buildCustomJacksonObjectMapper() { +    final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); +    converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); +    converter.getObjectMapper().setSerializationInclusion(Include.NON_NULL); +     +    converter.getObjectMapper().registerModule(new JavaTimeModule()); +    converter.getObjectMapper().configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); +    return converter; + +  } + +  @Nonnull +  private ResponseErrorHandler buildErrorHandler() { +    return new ResponseErrorHandler() { + +      @Override +      public boolean hasError(ClientHttpResponse response) throws IOException { +        return response.getStatusCode().is4xxClientError() +            || response.getStatusCode().is5xxServerError(); + +      } + +      @Override +      public void handleError(ClientHttpResponse response) throws IOException { +        // TODO: opimize errorHandling based on response info's from real ERnP + +        List<String> serverId = response.getHeaders().getOrEmpty(ERNP_RESPONSE_HEADER_SERVER_ID); +        log.warn("Receive http-error: {} from ERnP with serverTransactionId {}", +            response.getRawStatusCode(), serverId.isEmpty() ? "'not set'" : serverId.get(0)); +        log.warn("  Full ERnP response-body: {}", IOUtils.toString(response.getBody(), "UTF-8"));               +        throw new ErnpRestCommunicationException(response.getRawStatusCode()); +         +      } +    }; +  } + +  @Nonnull +  private HttpClientConfiguration buildHttpClientConfiguration() throws EaafException { +    final HttpClientConfiguration config = new HttpClientConfiguration(FRIENDLYNAME_HTTP_CLIENT); +    config.setAuthMode(ClientAuthMode.SSL.getMode()); + +    // Set keystore configuration +    config.buildKeyStoreConfig( +        basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_TYPE), +        basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PATH), +        basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PASSWORD), +        basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_NAME)); + +    // Set key information +    config.setSslKeyAlias( +        basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYS_ALIAS)); +    config.setSslKeyPassword( +        basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEY_PASSWORD)); + +    // Set connection parameters +    // TODO: update EAAF-components to allow custom HTTP Connection-Timeouts + +    return config; +  } + +  @AllArgsConstructor +  @Getter +  public static class ErnpRegisterResult { +    private final List<RegisterResult> personResult; + +  } + +  private GenericRequestParams buildGenericRequestParameters(String operationIdentifier) { +    return GenericRequestParams.builder() +        .clientBehkz(basicConfig.getBasicConfiguration( +            Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR)) +        .clientName(MessageFormat.format(Constants.CLIENT_INFO, versionHolder.getVersion())) +        .clientRequestTime(OffsetDateTime.now()) +        .clientRequestId(TransactionIdUtils.getTransactionId() + "_" + operationIdentifier) +        .build(); + +  } + +  @Builder +  @Getter +  private static class GenericRequestParams { +    String clientBehkz; +    String clientName; +    OffsetDateTime clientRequestTime; +    String clientRequestId; + +  } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java new file mode 100644 index 00000000..7a957531 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java @@ -0,0 +1,114 @@ +/* + * Copyright 2020 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp; + +import javax.annotation.Nonnull; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +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.exception.EidasSAuthenticationException; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; + +public interface IErnpClient { + +  /** +   * Search person based on eIDAS personal identifier. +   *  +   * @param personIdentifier Full eIDAS personal identifier with prefix +   * @param citizenCountryCode CountryCode of the eIDAS proxy-service +   * @return Search result but never <code>null</code> +   * @throws EidasSAuthenticationException In case of a communication error  +   */ +  @Nonnull +  ErnpRegisterResult searchWithPersonIdentifier(@Nonnull String personIdentifier,  +      @Nonnull String citizenCountryCode) throws EidasSAuthenticationException; + +  /** +   * Search person based on eIDSA MDS information. +   *  +   * @param givenName eIDAS given name +   * @param familyName eIDAS principle name +   * @param dateOfBirth eIDAS date-of-birth +   * @param citizenCountryCode CountryCode of the eIDAS proxy-service +   * @return Search result but never <code>null</code> +   * @throws EidasSAuthenticationException In case of a communication error  +   */ +  @Nonnull +  ErnpRegisterResult searchWithMds(@Nonnull String givenName, @Nonnull String familyName,  +      @Nonnull String dateOfBirth, @Nonnull String citizenCountryCode)  +      throws EidasSAuthenticationException; + +  /** +   * Search person based on country-specific natural person set. +   *  +   * @param personSearchDao Specific set of natural person informations. +   * @param citizenCountryCode CountryCode of the eIDAS proxy-service +   * @return Search result but never <code>null</code> +   * @throws EidasSAuthenticationException In case of a communication error  +   */ +  @Nonnull +  ErnpRegisterResult searchCountrySpecific(@Nonnull PersonSuchenRequest personSearchDao,  +      @Nonnull String citizenCountryCode) throws EidasSAuthenticationException; + +  /** +   * Update ERnP entry to KITT existing ERnP identity with this eIDAS authentication. +   *  +   * @param registerResult Already matched eIDAS identity that should be KITT +   * @param eidData eIDAS eID information from current authentication process  +   * @return Update result but never <code>null</code> +   * @throws EidasSAuthenticationException In case of a communication error  +   */ +  @Nonnull +  ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) +      throws EidasSAuthenticationException; + +   +  /** +   * Add new entry into ERnP by using identity from this eIDAS authentication. +   *  +   * @param eidData eIDAS eID information from current authentication process  +   * @return Update result but never <code>null</code> +   * @throws EidasSAuthenticationException In case of a communication error  +   */ +  @Nonnull +  ErnpRegisterResult add(SimpleEidasData eidData) throws EidasSAuthenticationException; +   +   +  /** +   * Search person based on address information. +   *  +   * @param givenName eIDAS given name +   * @param familyName eIDAS principle name +   * @param dateOfBirth eIDAS date-of-birth +   * @param zipcode ZipCode +   * @param city City +   * @param street Street +   * @return Search result but never <code>null</code> +   */ +  @Nonnull +  ErnpRegisterResult searchWithResidenceData(String givenName, String familyName,  +      String dateOfBirth, String zipcode, String city, String street); + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java index 397cbe46..bd1eb13e 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java @@ -111,28 +111,6 @@ public class SzrClient extends AbstractSoapClient {    final ObjectMapper mapper = new ObjectMapper(); -  /** -   * Get IdentityLink of a person. -   * -   * -   * @param eidData minimum dataset of person -   * @return IdentityLink -   * @throws SzrCommunicationException In case of a SZR error -   */ -  public IdentityLinkType getIdentityLinkInRawMode(SimpleEidasData eidData) -      throws SzrCommunicationException { -    try { -      final GetIdentityLinkEidas getIdl = new GetIdentityLinkEidas(); -      getIdl.setPersonInfo(generateSzrRequest(eidData)); - -      return getIdentityLinkGeneric(getIdl); - -    } catch (final Exception e) { -      log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e); -      throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e); - -    } -  }    /**     * Get IdentityLink of a person. @@ -206,33 +184,6 @@ public class SzrClient extends AbstractSoapClient {      }      return resp;    } - -  /** -   * Request a encrypted baseId from SZR. -   * -   * <b>Note</b>: Previously, this method did create a new ERnP entry, if it did not exist. This is -   * <b>not</b> the case any more. See {@link #createNewErnpEntry(SimpleEidasData)} for that functionality. -   * -   * @param eidData Minimum dataset of person -   * @return encrypted baseId -   * @throws SzrCommunicationException    In case of a SZR error -   */ -  public String getEncryptedStammzahl(final SimpleEidasData eidData) -      throws SzrCommunicationException { -    final String resp; -    try { -      resp = this.szr.getStammzahlEncrypted(generateSzrRequest(eidData), false); -    } catch (SZRException_Exception e) { -      throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e); -    } - -    if (StringUtils.isEmpty(resp)) { -      throw new SzrCommunicationException("ernb.01", new Object[]{"Stammzahl response empty"}); // TODO error handling -    } - -    return resp; - -  }    /**     * Request a encrypted baseId from SZR. diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java index c4e8ece0..f3c32c96 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java @@ -29,6 +29,7 @@ import javax.annotation.Nonnull;  import javax.annotation.Nullable;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient.ZmrRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput;  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.exception.EidasSAuthenticationException; @@ -80,6 +81,23 @@ public interface IZmrClient {            throws EidasSAuthenticationException;    /** +   * Search person based on MDS information and Austrian residence. +   *  +   * @param zmrProzessId zmrProzessId zmrProzessId ProcessId from ZMR or <code>null</code> if no processId exists +   * @param givenName eIDAS given name +   * @param familyName eIDAS principle name +   * @param dateOfBirth eIDAS date-of-birth +   * @param citizenCountryCode citizenCountryCode CountryCode of the eIDAS proxy-service +   * @param address Address information for searching +   * @return Search result but never <code>null</code> +   * @throws EidasSAuthenticationException In case of a communication error  +   */ +  @Nonnull +  ZmrRegisterResult searchWithResidenceData(@Nullable BigInteger zmrProzessId, @Nonnull String givenName,  +      @Nonnull String familyName, @Nonnull String dateOfBirth, @Nonnull String citizenCountryCode,  +      @Nonnull AdresssucheOutput address) throws EidasSAuthenticationException; +   +  /**     * Update ZMR entry to KITT existing ZMR identity with this eIDAS authentication.     *      * @param zmrProzessId zmrProzessId ProcessId from ZMR or <code>null</code> if no processId exists @@ -92,7 +110,4 @@ public interface IZmrClient {    ZmrRegisterResult update(@Nullable BigInteger zmrProzessId, RegisterResult registerResult, SimpleEidasData eidData)        throws EidasSAuthenticationException; -  ZmrRegisterResult searchWithResidenceData(@Nullable BigInteger zmrProzessId, String givenName, String familyName,  -      String dateOfBirth, String zipcode, String city, String street); -  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java index 711226e2..8dbd0632 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java @@ -24,6 +24,7 @@ import org.springframework.lang.Nullable;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.AbstractSoapClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput;  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.exception.EidasSAuthenticationException; @@ -56,6 +57,8 @@ import at.gv.bmi.namespace.zmr_su.zmr._20040201.SuchkriterienType;  import at.gv.e_government.reference.namespace.persondata.de._20040201.IdentificationType;  import at.gv.e_government.reference.namespace.persondata.de._20040201.NatuerlichePersonTyp;  import at.gv.e_government.reference.namespace.persondata.de._20040201.PersonenNameTyp; +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.exceptions.EaafAuthenticationException;  import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; @@ -95,12 +98,12 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {        "Searching " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER;    private static final String PROCESS_SEARCH_MDS_ONLY = "Searching with MDS only";    private static final String PROCESS_SEARCH_COUNTRY_SPECIFIC = "Searching {0} specific"; +  private static final String PROCESS_SEARCH_BY_RESIDENCE = "Searching by residence";    private static final String PROCESS_KITT_GENERAL = "KITT general-processing";    private static final String PROCESS_KITT_IDENITIES_GET = "KITT get-latest-version";    private static final String PROCESS_KITT_IDENITIES_UPDATE = "KITT update dataset"; -  private static final String CLIENT_INFO = "eIDAS MS-Connector v{0}";    private static final String CLIENT_DEFAULT = "ZMR Client"; @@ -174,15 +177,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {        // set eIDAS person information        final PersonSuchenRequest searchPersonReq = new PersonSuchenRequest();        req.setPersonSuchenRequest(searchPersonReq); - -      final NatuerlichePersonTyp searchNatPerson = new NatuerlichePersonTyp(); -      searchPersonReq.setNatuerlichePerson(searchNatPerson); -      final PersonenNameTyp searchNatPersonName = new PersonenNameTyp(); -      searchNatPerson.setPersonenName(searchNatPersonName); - -      searchNatPersonName.setFamilienname(familyName); -      searchNatPersonName.setVorname(givenName); -      searchNatPerson.setGeburtsdatum(dateOfBirth); +      searchPersonReq.setNatuerlichePerson(buildSearchNatPerson(givenName, familyName, dateOfBirth));        // set work-flow client information        req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_TASK_SEARCH, zmrProzessId)); @@ -269,8 +264,12 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {        Collection<? extends EidasIdentitaetAnlageType> eidasDocumentToAdd =             selectEidasDocumentsToAdd(zmrPersonToKitt, eidData); +      /*TODO: Is there a requirement to change 'eIDAS-Documents'? +       *      We add MDS information as 'eIDAS-Documents' too. Maybe, we should update that in a later version.   +       */ +              if (eidasDocumentToAdd.isEmpty()) { -        log.info("Find no eIDAS document for update during: {}. Looks strange but nothing todo",  +        log.info("Find no eIDAS document for update during: {}. Nothing todo on ZMR side",               PROCESS_KITT_GENERAL);          return new ZmrRegisterResult(Arrays.asList(registerResult), zmrProzessId); @@ -297,12 +296,49 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {      }    } -   +        @Override    public ZmrRegisterResult searchWithResidenceData(BigInteger zmrProzessId, String givenName, String familyName,  -      String dateOfBirth, String zipcode, String city, String street) { -    // TODO Auto-generated method stub -    return null; +      String dateOfBirth, String citizenCountryCode, AdresssucheOutput address) +          throws EidasSAuthenticationException { +    try { +      // build search request +      final RequestType req = new RequestType(); + +      // set person information +      final PersonSuchenRequest searchPersonReq = new PersonSuchenRequest(); +      req.setPersonSuchenRequest(searchPersonReq); +      searchPersonReq.setNatuerlichePerson(buildSearchNatPerson(givenName, familyName, dateOfBirth));        +      searchPersonReq.setPostAdresse(buildSearchAddress(address)); + +      // set work-flow client information +      req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_TASK_SEARCH, zmrProzessId)); +      req.setClientInfo(generateClientInfos()); + +      // set additionl search parameters +      searchPersonReq.setPersonensucheInfo(generateSearchCriteria( +          PROCESS_SEARCH_BY_RESIDENCE, false, true, false)); + +      // request ZMR +      log.trace("Requesting ZMR for '{}' operation", PROCESS_SEARCH_BY_RESIDENCE); +      final ResponseType resp = zmrClient.service(req, null); + +      // parse ZMR response +      return processZmrResponse(resp, citizenCountryCode, false, PROCESS_SEARCH_BY_RESIDENCE); + +    } catch (final ServiceFault e) { +      final String errorMsg = extractReasonFromError(e); +      log.warn(LOGMSG_ZMR_ERROR, PROCESS_SEARCH_BY_RESIDENCE, errorMsg); +      throw new ZmrCommunicationException(ERROR_MATCHING_01, new Object[] { errorMsg }, e); + +    } catch (EidasSAuthenticationException e) { +      throw e; +       +    } catch (final Exception e) { +      log.warn(LOGMSG_ZMR_RESP_PROCESS, PROCESS_SEARCH_BY_RESIDENCE, e.getMessage()); +      throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); + +    }    }    @PostConstruct @@ -429,7 +465,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {      clientInfo.setOrganisation(clientOrganisation);      // set client information -    clientInfo.setClient(MessageFormat.format(CLIENT_INFO, versionHolder.getVersion())); +    clientInfo.setClient(MessageFormat.format(Constants.CLIENT_INFO, versionHolder.getVersion()));      // set Behoerdennummer as organization identifier      clientOrganisation.setBehoerdenNr(basicConfig.getBasicConfiguration( @@ -465,7 +501,6 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {        return new ZmrRegisterResult(Collections.emptyList(), extractZmrProcessId(resp.getWorkflowInfoServer()));      } else { -      // TODO: what we to with ERnP results?        log.debug("Get #{} person results from '{}' operation",            searchPersonResp.getPersonensuchergebnis().getGefundeneSaetze(), processStepFiendlyname); @@ -687,6 +722,43 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {      }    } +  private NatuerlichePersonTyp buildSearchNatPerson(String givenName, String familyName, String dateOfBirth) { +    final NatuerlichePersonTyp searchNatPerson = new NatuerlichePersonTyp();     +    final PersonenNameTyp searchNatPersonName = new PersonenNameTyp(); +    searchNatPerson.setPersonenName(searchNatPersonName); +    searchNatPersonName.setFamilienname(familyName); +    searchNatPersonName.setVorname(givenName); +    searchNatPerson.setGeburtsdatum(dateOfBirth); +    return searchNatPerson; +     +  } +   +  private PostAdresseTyp buildSearchAddress(AdresssucheOutput address) { +    PostAdresseTyp postAdresse = new PostAdresseTyp(); +    if (StringUtils.isNotBlank(address.getPostleitzahl())) { +      postAdresse.setPostleitzahl(address.getPostleitzahl()); +    } +    if (StringUtils.isNotBlank(address.getMunicipality())) { +      postAdresse.setGemeinde(address.getMunicipality()); +    } +    if (StringUtils.isNotBlank(address.getVillage())) { +      postAdresse.setOrtschaft(address.getVillage()); +    } +    if (StringUtils.isNotBlank(address.getStreet()) || StringUtils.isNotBlank(address.getNumber())) { +      ZustelladresseTyp zustelladresse = new ZustelladresseTyp(); +      if (StringUtils.isNotBlank(address.getStreet())) { +        zustelladresse.setStrassenname(address.getStreet()); +      } +      if (StringUtils.isNotBlank(address.getNumber())) { +        zustelladresse.setOrientierungsnummer(address.getNumber()); +      } +      postAdresse.setZustelladresse(zustelladresse); +    } +     +    return postAdresse; +     +  } +      private Collection<? extends EidasIdentitaetAnlageType> selectEidasDocumentsToAdd(        PersonErgebnisType zmrPersonToKitt, SimpleEidasData eidData) { @@ -698,6 +770,14 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {          Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth(), false);      addEidasDocumentIfNotAvailable(result, zmrPersonToKitt, eidData.getCitizenCountryCode(),           Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName(), false); +     +    // add MDS attributes as 'eIDAS-Documents' too, because ZMR does not allow a MDS update on regular places. +    addEidasDocumentIfNotAvailable(result, zmrPersonToKitt, eidData.getCitizenCountryCode(),  +        Constants.eIDAS_ATTRURN_CURRENTGIVENNAME, eidData.getGivenName(), false); +    addEidasDocumentIfNotAvailable(result, zmrPersonToKitt, eidData.getCitizenCountryCode(),  +        Constants.eIDAS_ATTRURN_CURRENTFAMILYNAME, eidData.getFamilyName(), false); +    addEidasDocumentIfNotAvailable(result, zmrPersonToKitt,  eidData.getCitizenCountryCode(),  +        Constants.eIDAS_ATTRURN_DATEOFBIRTH, eidData.getDateOfBirth(), false);      return result; diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java new file mode 100644 index 00000000..6dcd4879 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java @@ -0,0 +1,269 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.asitplus.eidas.specific.modules.auth.eidas.v2.controller; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.CompareToBuilder; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.asitplus.eidas.specific.connector.gui.StaticGuiBuilderConfiguration; +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.gui.ISpringMvcGuiFormBuilder; +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.EaafException; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * Default process-engine signaling controller. + * + * @author tlenz + */ +@Controller +@Slf4j +public class AdresssucheController { + +  public static final String PARAM_POSTLEITZAHL = "postleitzahl"; +  public static final String PARAM_MUNIPICALITY = "municipality"; +  public static final String PARAM_VILLAGE = "village"; +  public static final String PARAM_STREET = "street"; +  public static final String PARAM_NUMBER = "number"; +     +  @Autowired +  private ISpringMvcGuiFormBuilder guiBuilder; + +  @Autowired +  private IConfiguration basicConfig; + +  @Autowired +  private ResourceLoader resourceLoader; + +  @Autowired +  private ZmrAddressSoapClient client; + +  @Autowired +  private IPendingRequestIdGenerationStrategy pendingReqGeneration; + +  /** +   * Show the "residency.html" directly. +   * TODO Remove this after testing. +   */ +  @RequestMapping(value = {"/test"}, method = {RequestMethod.GET}) +  public void test(HttpServletRequest request, HttpServletResponse response) throws GuiBuildException, EaafException { +    final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( +        basicConfig, +        "http://localhost:8080/ms_connector/", +        basicConfig.getBasicConfiguration(//TODO +            MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_RESIDENCY, +            MsEidasNodeConstants.TEMPLATE_HTML_RESIDENCY), +        MsEidasNodeConstants.ENDPOINT_RESIDENCY_INPUT, +        resourceLoader); +    config.putCustomParameter(null, "pendingid", pendingReqGeneration.generateExternalPendingRequestId()); +    guiBuilder.build(request, response, config, "Query Austrian residency"); +  } + +  /** +   * Show the "other_login_method.html" directly. +   * TODO Remove this after testing. +   */ +  @RequestMapping(value = {"/olm"}, method = {RequestMethod.GET}) +  public void otherloginmethod(HttpServletRequest request, HttpServletResponse response) throws GuiBuildException, +      EaafException { +    final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( +        basicConfig, +        "http://localhost:8080/ms_connector/", +        basicConfig.getBasicConfiguration(//TODO +            MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_OTHER_LOGIN_METHOD_SELECTION, +            MsEidasNodeConstants.TEMPLATE_HTML_OTHERLOGINMETHODS), +        MsEidasNodeConstants.ENDPOINT_OTHER_LOGIN_METHOD_SELECTION, +        resourceLoader); +    config.putCustomParameter(null, "pendingid", pendingReqGeneration.generateExternalPendingRequestId()); +    guiBuilder.build(request, response, config, "Other Login Method"); +  } + +  /** +   * Show the "country_selection.html" directly. +   * TODO Remove this after testing. +   */ +  @RequestMapping(value = {"/country"}, method = {RequestMethod.GET}) +  public void countryselection(HttpServletRequest request, HttpServletResponse response) throws GuiBuildException, +      EaafException { +    final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( +        basicConfig, +        "http://localhost:8080/ms_connector/", +        basicConfig.getBasicConfiguration(//TODO +            MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_CCSELECTION, +            MsEidasNodeConstants.TEMPLATE_HTML_COUNTRYSELECTION), +        MsEidasNodeConstants.ENDPOINT_COUNTRYSELECTION, +        resourceLoader); +    config.putCustomParameter(null, "pendingid", pendingReqGeneration.generateExternalPendingRequestId()); +    guiBuilder.build(request, response, config, "Country Selection"); +  } + +  /** +   * Performs search for addresses in ZMR. +   */ +  @RequestMapping(value = {"/residency/search"}, method = {RequestMethod.POST}) +  public ResponseEntity<AdresssucheResult> search( +      @RequestParam(PARAM_POSTLEITZAHL) String postleitzahl, +      @RequestParam(PARAM_MUNIPICALITY) String municipality, +      @RequestParam(PARAM_VILLAGE) String village, +      @RequestParam(PARAM_STREET) String street, +      @RequestParam(PARAM_NUMBER) String number, +      @RequestParam(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID) String pendingId) { +    log.info("Search with '{}', '{}', '{}', '{}', '{}'", +        postleitzahl.replaceAll("[\r\n]", ""), +        municipality.replaceAll("[\r\n]", ""), +        village.replaceAll("[\r\n]", ""), +        street.replaceAll("[\r\n]", ""), +        number.replaceAll("[\r\n]", ""));     +    try { +      pendingReqGeneration.validateAndGetPendingRequestId(pendingId); +       +    } catch (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); +      return ResponseEntity.ok(output); +       +    } catch (EidasSAuthenticationException e) { +      log.warn("Search failed", e); +      return ResponseEntity.badRequest().build(); +       +    } +  } + +  private AdresssucheResult buildResponse(ZmrAddressSoapClient.AddressInfo searchOutput) { +    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() +        .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()); +     +  } + +  private Adressdaten buildSearchInput(String postleitzahl, +                                       String municipality, +                                       String village, +                                       String street, +                                       String number) { +    PostAdresseTyp postAdresse = new PostAdresseTyp(); +    if (StringUtils.isNotBlank(postleitzahl)) { +      postAdresse.setPostleitzahl(postleitzahl); +    } +    if (StringUtils.isNotBlank(municipality)) { +      postAdresse.setGemeinde(municipality); +    } +    if (StringUtils.isNotBlank(village)) { +      postAdresse.setOrtschaft(village); +    } +    if (StringUtils.isNotBlank(street) || StringUtils.isNotBlank(number)) { +      ZustelladresseTyp zustelladresse = new ZustelladresseTyp(); +      if (StringUtils.isNotBlank(street)) { +        zustelladresse.setStrassenname(street); +      } +      if (StringUtils.isNotBlank(number)) { +        zustelladresse.setOrientierungsnummer(number); +      } +      postAdresse.setZustelladresse(zustelladresse); +    } +    Adressdaten searchInput = new Adressdaten(); +    searchInput.setPostAdresse(postAdresse); +    return searchInput; +     +  } + +  @Data +  @AllArgsConstructor +  public static class AdresssucheResult { +    private final Collection<AdresssucheOutput> results; +    private final int resultCount; +  } + +  @Data +  @AllArgsConstructor +  @Builder +  public static class AdresssucheOutput implements Comparable<AdresssucheOutput> { +    private final String postleitzahl; +    private final String municipality; +    private final String village; +    private final String street; +    private final String number; + +    @Override +    public int compareTo(@NotNull AdresssucheOutput o) { +      return new CompareToBuilder() +          .append(this.postleitzahl, o.postleitzahl) +          .append(this.municipality, o.municipality) +          .append(this.village, o.village) +          .append(this.street, o.street) +          .append(this.number, o.number) +          .toComparison(); +    } +  } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java index 1e8fcecf..1dcea7fc 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java @@ -1,5 +1,7 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable; +  import lombok.Builder;  import lombok.Getter; @@ -11,7 +13,9 @@ import lombok.Getter;   */  @Getter  @Builder -public class MatchedPersonResult { +public class MatchedPersonResult implements Serializable { + +  private static final long serialVersionUID = 9110998952621456281L;    /**     * Matched person result from matching result. diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java index aa82d806..e5878ff3 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java @@ -23,6 +23,7 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable;  import java.util.List;  import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType; @@ -31,8 +32,10 @@ import lombok.Getter;  @Builder  @Getter -public class RegisterResult { +public class RegisterResult implements Serializable { +  private static final long serialVersionUID = 762728480185716130L; +    // MDS    private final List<String> pseudonym;    private final String givenName; diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java index 5ad92507..aca5025f 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java @@ -23,14 +23,19 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable; + +import org.apache.commons.lang3.builder.EqualsBuilder; +  import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;  import lombok.Builder;  import lombok.Data; -import org.apache.commons.lang3.builder.EqualsBuilder;  @Data -@Builder -public class SimpleEidasData { +@Builder(toBuilder = true) +public class SimpleEidasData implements Serializable { + +  private static final long serialVersionUID = 2848914124372968418L;    /**     * Full eIDAS personal identifier with prefix. @@ -68,8 +73,11 @@ public class SimpleEidasData {          .append(result.getGivenName(), givenName)          .append(result.getFamilyName(), familyName)          .append(result.getDateOfBirth(), dateOfBirth) -        .isEquals() -        && result.getPseudonym().stream().anyMatch(el -> el.equals(pseudonym)); +        .appendSuper(result.getPseudonym().stream().anyMatch(el -> el.equals(pseudonym))) +        .appendSuper(checkOptionalAttributes(result.getPlaceOfBirth(), placeOfBirth)) +        .appendSuper(checkOptionalAttributes(result.getBirthName(), birthName)) +        .isEquals(); +            }    /** @@ -84,5 +92,17 @@ public class SimpleEidasData {          .isEquals();    } +  /** +   * Check if eIDAS attribute is available. +   *  +   * @param registerData Attribute value from register +   * @param eidasData Attribute value from eIDAS +   * @return <code>true</code> if eidasData is <code>null</code> or eidasData does not match to register value,  +   *     otherwise <code>false</code>  +   */ +  private static boolean checkOptionalAttributes(String registerData, String eidasData) { +    return eidasData == null || eidasData.equals(registerData); +     +  }  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java index 92e727ea..54cb3f31 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java @@ -23,6 +23,8 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable; +  import org.apache.commons.lang3.builder.EqualsBuilder;  import lombok.Builder; @@ -30,7 +32,9 @@ import lombok.Data;  @Data  @Builder -public class SimpleMobileSignatureData { +public class SimpleMobileSignatureData implements Serializable { + +  private static final long serialVersionUID = 7775305733438275312L;    private final String bpk;    private final String givenName; diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java index 77f5e3cd..dabb73dc 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java @@ -24,51 +24,58 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp;  import java.util.Collections; -import java.util.List;  import org.springframework.stereotype.Service; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient;  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.exception.EidasSAuthenticationException; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest;  @Service("ErnbClientForeIDAS")  public class DummyErnpClient implements IErnpClient { +      @Override -  public List<RegisterResult> searchWithPersonIdentifier(String personIdentifier) { -    return Collections.emptyList(); +  public ErnpRegisterResult searchWithPersonIdentifier(String personIdentifier, String citizenCountryCode) +      throws EidasSAuthenticationException { +    return buildEmptyResult();    }    @Override -  public List<RegisterResult> searchWithMds(String givenName, String familyName, String dateOfBirth) { -    //TODO will I only receive matches where all three values match perfectly? -    return Collections.emptyList(); +  public ErnpRegisterResult searchWithMds(String givenName, String familyName, String dateOfBirth, +      String citizenCountryCode) throws EidasSAuthenticationException { +    return buildEmptyResult();    }    @Override -  public List<RegisterResult> searchDeSpecific(String givenName, String familyName, String dateOfBirth, -                                                    String birthPlace, String birthName) { -    //TODO -    return Collections.emptyList(); +  public ErnpRegisterResult searchCountrySpecific(PersonSuchenRequest personSearchDao, +      String citizenCountryCode) throws EidasSAuthenticationException { +    return buildEmptyResult();    }    @Override -  public List<RegisterResult> searchItSpecific(String taxNumber) { -    //TODO -    return Collections.emptyList(); +  public ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) +      throws EidasSAuthenticationException { +    return buildEmptyResult();    }    @Override -  public RegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) { -    //TODO -    return null; +  public ErnpRegisterResult searchWithResidenceData(String givenName, String familyName, String dateOfBirth, +      String zipcode, String city, String street) { +    return buildEmptyResult();    } -  @Override -  public List<RegisterResult> searchWithBpkZp(String bpkzp) { -    //TODO -    return Collections.emptyList(); +  private static ErnpRegisterResult buildEmptyResult() { +    return new ErnpRegisterResult(Collections.emptyList()); +        } +  @Override +  public ErnpRegisterResult add(SimpleEidasData eidData) throws EidasSAuthenticationException { +    return buildEmptyResult(); +  }  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java deleted file mode 100644 index b2a9005b..00000000 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020 A-SIT Plus GmbH - * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, - * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "License"); - * You may not use this work except in compliance with the License. - * You may obtain a copy of the License at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - -package at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp; - -import java.util.List; - -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; - -public interface IErnpClient { - -  List<RegisterResult> searchWithPersonIdentifier(String personIdentifier); - -  List<RegisterResult> searchWithMds(String givenName, String familyName, String dateOfBirth); - -  List<RegisterResult> searchDeSpecific(String givenName, String familyName, String dateOfBirth, -                                             String birthPlace, String birthName); - -  List<RegisterResult> searchItSpecific(String taxNumber); - -  RegisterResult update(RegisterResult registerResult, SimpleEidasData eidData); - -  List<RegisterResult> searchWithBpkZp(String bpkzp); - -} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java new file mode 100644 index 00000000..566a8fa4 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java @@ -0,0 +1,29 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.exception; + +import java.io.IOException; + +import lombok.Getter; + +/** + * ERnP exception in case of a REST communication error. + *  + * @author tlenz + * + */ +public class ErnpRestCommunicationException extends IOException { +  private static final long serialVersionUID = -3178689122077228976L; +   +  @Getter +  int httpStatusCode; +   +  /** +   * ERnP communication error on HTTP REST level. +   *  +   * @param rawStatusCode HTTP statuscode +   */ +  public ErnpRestCommunicationException(int rawStatusCode) { +    super("ERnP service answers with an error and HTTP status-code: " + rawStatusCode); +    this.httpStatusCode = rawStatusCode;     +     +  }   +} 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 047d75ae..c3bf4309 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 @@ -7,19 +7,23 @@ import java.util.List;  import javax.annotation.Nonnull;  import org.jetbrains.annotations.Nullable; +import org.springframework.lang.NonNull;  import org.springframework.stereotype.Service;  import com.google.common.collect.Streams; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient;  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.controller.AdresssucheController.AdresssucheOutput;  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.exception.ZmrCommunicationException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.CountrySpecificDetailSearchProcessor; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest;  import lombok.AllArgsConstructor;  import lombok.Getter;  import lombok.RequiredArgsConstructor; @@ -77,8 +81,8 @@ public class RegisterSearchService {        final ZmrRegisterResult resultsZmr = zmrClient.searchWithPersonIdentifier(            operationStatus != null ? operationStatus.getZmrProcessId() : null,             eidasData.getPseudonym(), eidasData.getCitizenCountryCode()); -      final List<RegisterResult> resultsErnp = ernpClient.searchWithPersonIdentifier( -          eidasData.getPersonalIdentifier()); +      final ErnpRegisterResult resultsErnp = ernpClient.searchWithPersonIdentifier( +          eidasData.getPseudonym(), eidasData.getCitizenCountryCode());        return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultsErnp); @@ -104,9 +108,9 @@ public class RegisterSearchService {            zmrClient.searchWithMds(operationStatus.getZmrProcessId(), eidasData.getGivenName(),                eidasData.getFamilyName(), eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode()); -      final List<RegisterResult> resultsErnp = -          ernpClient.searchWithMds(eidasData.getGivenName(), eidasData.getFamilyName(), eidasData -              .getDateOfBirth()); +      final ErnpRegisterResult resultsErnp = +          ernpClient.searchWithMds(eidasData.getGivenName(), +              eidasData.getFamilyName(), eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode());        return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultsErnp); @@ -132,16 +136,22 @@ public class RegisterSearchService {      try {        @Nullable final CountrySpecificDetailSearchProcessor ccSpecificProcessor = findSpecificProcessor(eidasData);        if (ccSpecificProcessor != null) { -        log.debug("Selecting country-specific search processor: {}", ccSpecificProcessor.getName()); +        log.debug("Selecting country-specific search processor: {}", ccSpecificProcessor.getName());         +        PersonSuchenRequest ccSpecificSearchReq = ccSpecificProcessor.generateSearchRequest(eidasData); +         +        // search in ZMR          final ZmrRegisterResult resultsZmr =              zmrClient.searchCountrySpecific(operationStatus.getZmrProcessId(), -                ccSpecificProcessor.generateSearchRequest(eidasData), -                eidasData.getCitizenCountryCode()); -        return RegisterStatusResults.fromZmr(resultsZmr); +                ccSpecificSearchReq, eidasData.getCitizenCountryCode()); + +        //search in ERnP +        ErnpRegisterResult resultErnp = ernpClient.searchCountrySpecific( +            ccSpecificSearchReq, eidasData.getCitizenCountryCode()); +                 +        return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultErnp);        } else { -        // TODO: add search procesfor for ERnP searching -        return RegisterStatusResults.fromErnp(operationStatus, Collections.emptyList()); +        return RegisterStatusResults.fromEmpty(operationStatus);        } @@ -156,18 +166,29 @@ public class RegisterSearchService {     * 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 +   * @param eidasData Receive eIDAS eID information +   * @param address Address information provided by user     * @return Results from ZMR or ERnP search +   * @throws WorkflowException In case of a register interaction error     */ -  public RegisterStatusResults 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 RegisterStatusResults.fromZmr(resultsZmr); +  public RegisterStatusResults searchWithResidence(RegisterOperationStatus operationStatus, SimpleEidasData eidasData,  +      AdresssucheOutput address) throws WorkflowException {     +    try { +      final ZmrRegisterResult resultsZmr = zmrClient.searchWithResidenceData( +          operationStatus.getZmrProcessId(), eidasData.getGivenName(), eidasData.getFamilyName(), +          eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode(), address); +      /* ERnP search is not used here,  +       * because we only search for people with Austrian residence and they are in ZMR only   +       */ +     +      return RegisterStatusResults.fromZmr(resultsZmr); +       +    } catch (final EidasSAuthenticationException e) { +      throw new WorkflowException("searchWithResidenceInformation", e.getMessage(), +          !(e instanceof ZmrCommunicationException), e); + +    }    }    /** @@ -178,34 +199,49 @@ public class RegisterSearchService {     * @param initialEidasData Received eidas data from initial authn     * @return     */ +  @NonNull    public RegisterStatusResults step7aKittProcess(RegisterStatusResults registerResult,                                                   SimpleEidasData initialEidasData) throws WorkflowException {      log.trace("Starting step7aKittProcess"); -    // TODO verify with which data this method gets called +     +    // check if only one single result was found      if (registerResult.getResultCount() != 1) {        throw new WorkflowException("step7aKittProcess", "getResultCount() != 1"); +            } +     +    // perform updated operation in respect to register results      try {        if (registerResult.getResultsZmr().size() == 1) {          RegisterResult entryZmr = registerResult.getResultsZmr().get(0);          ZmrRegisterResult updateZmr = zmrClient              .update(registerResult.getOperationStatus().getZmrProcessId(), entryZmr, initialEidasData);          return RegisterStatusResults.fromZmr(updateZmr); +                } else {          RegisterResult entryErnp = registerResult.getResultsErnp().get(0); -        RegisterResult updateErnp = ernpClient.update(entryErnp, initialEidasData); -        return RegisterStatusResults.fromErnp(registerResult.operationStatus, Collections.singletonList(updateErnp)); +        ErnpRegisterResult updateErnp = ernpClient.update(entryErnp, initialEidasData); +        return RegisterStatusResults.fromErnp(registerResult.operationStatus, updateErnp); +                }      } catch (final EidasSAuthenticationException e) {        throw new WorkflowException("kittMatchedIdentitiess", e.getMessage(),            !(e instanceof ZmrCommunicationException), e); +            }    } -  //TODO: check this method, because it's different to 'step7aKittProcess'???    /**     * Automatic process to fix the register entries.     * Called when the alternative eIDAS authn leads to a match in a register. +   *  +   * <p>This method perform two additional operations: +   * <ul> +   *  <li>Use bPK to check if <i>altSearchResult</i> is part of <i>initialSearchResult</i>.</li> +   *  <li>Update register entry twice, be using information from alternative authentication <i>altEidasData</i> +   *      and from initial authentication <i>initialEidasData</i>.</li> +   * </ul> +   * </p>     *     * @param initialSearchResult Register results from initial authentication     * @param initialEidasData    Received eIDAS data from initial authentication @@ -263,9 +299,9 @@ public class RegisterSearchService {          ernpClient.update(entryErnp, initialEidasData);          // update ZMR entry by using eIDAS information from alternative authentication -        RegisterResult updateAlt = ernpClient.update(entryErnp, altEidasData); +        ErnpRegisterResult updateAlt = ernpClient.update(entryErnp, altEidasData); -        return RegisterStatusResults.fromErnp(altSearchResult.operationStatus, Collections.singletonList(updateAlt)); +        return RegisterStatusResults.fromErnp(altSearchResult.getOperationStatus(), updateAlt);        }      } catch (final EidasSAuthenticationException e) {        throw new WorkflowException("kittMatchedIdentitiess", e.getMessage(), @@ -373,13 +409,17 @@ public class RegisterSearchService {            result.getPersonResult(), Collections.emptyList());      } -    static RegisterStatusResults fromZmrAndErnp(ZmrRegisterResult result, List<RegisterResult> resultsErnp) { +    static RegisterStatusResults fromZmrAndErnp(ZmrRegisterResult result, ErnpRegisterResult resultErnp) {        return new RegisterStatusResults(new RegisterOperationStatus(result.getProcessId()), -          result.getPersonResult(), resultsErnp); +          result.getPersonResult(), resultErnp.getPersonResult());      } -    static RegisterStatusResults fromErnp(RegisterOperationStatus status, List<RegisterResult> resultsErnp) { -      return new RegisterStatusResults(status, Collections.emptyList(), resultsErnp); +    static RegisterStatusResults fromErnp(RegisterOperationStatus status, ErnpRegisterResult updateErnp) { +      return new RegisterStatusResults(status, Collections.emptyList(), updateErnp.getPersonResult()); +    } +     +    static RegisterStatusResults fromEmpty(RegisterOperationStatus status) { +      return new RegisterStatusResults(status, Collections.emptyList(), Collections.emptyList());      }    } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java index f021fae9..96aa9c51 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java @@ -23,6 +23,8 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED; +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON;  import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK;  import java.util.Map; @@ -78,6 +80,8 @@ import lombok.extern.slf4j.Slf4j;  @SuppressWarnings("PMD.TooManyStaticImports")  public class AlternativeSearchTask extends AbstractAuthServletTask { +  private static final String MSG_PROP_25 = "module.eidasauth.matching.25"; +      private final RegisterSearchService registerSearchService;    private final ICcSpecificEidProcessingService eidPostProcessor; @@ -200,6 +204,8 @@ public class AlternativeSearchTask extends AbstractAuthServletTask {        log.trace("'step12CountrySpecificSearch' ends with no result. Forward to GUI based matching step ... ");        log.debug("Forward to GUI based matching steps ... ");        executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +      executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_25); +      executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);       } else if (ccAltSearchResult.getResultCount() == 1) {        log.debug("'step12CountrySpecificSearch' find single result. Starting KITT operation ... "); diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java index c95c275e..0aba70d1 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java @@ -23,21 +23,16 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; -import java.io.IOException; -import java.io.InputStream;  import java.util.List;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import javax.xml.parsers.ParserConfigurationException;  import org.jetbrains.annotations.Nullable;  import org.jose4j.lang.JoseException;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Component;  import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException;  import com.fasterxml.jackson.core.JsonProcessingException; @@ -64,8 +59,6 @@ import at.gv.egiz.eaaf.core.impl.data.Pair;  import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;  import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;  import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import at.gv.egiz.eaaf.core.impl.utils.DomUtils; -import at.gv.egiz.eaaf.core.impl.utils.XPathUtils;  import lombok.Data;  import lombok.extern.slf4j.Slf4j;  import szrservices.IdentityLinkType; @@ -86,9 +79,6 @@ import szrservices.IdentityLinkType;   * <ul>   *     <li>{@link at.gv.egiz.eaaf.core.impl.idp.controller.tasks.FinalizeAuthenticationTask}</li>   * </ul> - * TODO Take Constants#DATA_SIMPLE_EIDAS and Constants#DATA_RESULT_MATCHING_BPK - * TODO Only do VSZ Erstellung and eidasBind -- this is always the end of the whole process - * TODO Move Eintragung to separate Task, as it does not happen every time   * @author tlenz   */  @Slf4j @@ -127,21 +117,17 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {        final SimpleEidasData eidData = MatchingTaskUtils.getInitialEidasData(pendingReq);        MatchedPersonResult matchedPersonData = MatchingTaskUtils.getFinalMatchingResult(pendingReq); +      // write log information based on current configuration        writeMdsLogInformation(eidData); -      if (basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) { -        buildDummyIdentityLink(eidData); +      //request SZR based on IDL or E-ID mode +      if (pendingReq.getServiceProviderConfiguration() +          .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false)) { +        executeEidMode(eidData, matchedPersonData);        } else { -        //request SZR based on IDL or E-ID mode -        if (pendingReq.getServiceProviderConfiguration() -            .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false)) { -          executeEidMode(eidData, matchedPersonData); +        executeIdlMode(eidData, matchedPersonData); -        } else { -          executeIdlMode(eidData, matchedPersonData); - -        }        }        storeGenericInfoToSession(eidData); @@ -192,16 +178,8 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {    private void executeEidMode(SimpleEidasData eidData, MatchedPersonResult matchedPersonData)        throws JsonProcessingException, EaafException, JoseException {      // get encrypted baseId -    String vsz; -    if (matchedPersonData != null) { -      log.debug("Requesting encrypted baseId by already matched person information ... "); -      vsz = szrClient.getEncryptedStammzahl(matchedPersonData); - -    } else { -      log.debug("Requesting encrypted baseId by using eIDAS information directly ... "); -      vsz = szrClient.createNewErnpEntry(eidData); - -    } +    log.debug("Requesting encrypted baseId by already matched person information ... "); +    String vsz = szrClient.getEncryptedStammzahl(matchedPersonData);      //write revision-Log entry and extended infos personal-identifier mapping      revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_VSZ_RECEIVED); @@ -224,21 +202,6 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {    } -  private void buildDummyIdentityLink(SimpleEidasData eidData) -      throws ParserConfigurationException, SAXException, IOException, EaafException { -    AuthProcessDataWrapper authProcessDataWrapper = MatchingTaskUtils.getAuthProcessDataWrapper(pendingReq); -    SzrResultHolder idlResult = createDummyIdentityLinkForTestDeployment(eidData); -    //inject personal-data into session -    authProcessDataWrapper.setIdentityLink(idlResult.getIdentityLink()); - -    // set bPK and bPKType into auth session -    authProcessDataWrapper.setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, extendBpkByPrefix( -        idlResult.getBpK(), pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier())); -    authProcessDataWrapper.setGenericDataToSession(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, -        pendingReq.getServiceProviderConfiguration() -            .getAreaSpecificTargetIdentifier()); -  } -    private void writeExtendedRevisionLogEntry(SimpleEidasData eidData, String personalIdentifier) {      // write ERnP input-data into revision-log      if (basicConfig.getBasicConfigurationBoolean( @@ -252,18 +215,8 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {    private SzrResultHolder requestSzrForIdentityLink(SimpleEidasData eidData,        MatchedPersonResult matchedPersonData) throws EaafException {      //request IdentityLink from SZR -    IdentityLinkType result; - -    if (matchedPersonData != null) { -      log.debug("Requesting encrypted baseId by already matched person information ... "); -      result = szrClient.getIdentityLinkInRawMode(matchedPersonData); - -    } else { -      log.debug("Requesting encrypted baseId by using eIDAS information directly ... "); -      result = szrClient.getIdentityLinkInRawMode(eidData); - -    } - +    log.debug("Requesting encrypted baseId by already matched person information ... "); +    IdentityLinkType result = szrClient.getIdentityLinkInRawMode(matchedPersonData);      final Element idlFromSzr = (Element) result.getAssertion();      final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlFromSzr).parseIdentityLink(); @@ -364,63 +317,4 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {      final String bpK;    } - -  /** -   * Build a dummy IdentityLink and a dummy bPK based on eIDAS information. -   * -   * <br><br> -   * <b>FOR LOCAL TESTING ONLY!!!</b> -   * -   * @param eidData Information from eIDAS response -   * @return IdentityLink and bPK -   * @throws ParserConfigurationException In case of an IDL processing error -   * @throws SAXException                 In case of an IDL processing error -   * @throws IOException                  In case of an IDL processing error -   * @throws EaafException                In case of a bPK generation error -   */ -  private SzrResultHolder createDummyIdentityLinkForTestDeployment(SimpleEidasData eidData) -      throws ParserConfigurationException, SAXException, IOException, EaafException { -    log.warn("SZR-Dummy IS ACTIVE! IdentityLink is NOT VALID!!!!"); -    // create fake IdL -    // - fetch IdL template from resources -    final InputStream s = CreateIdentityLinkTask.class -        .getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml"); -    final Element idlTemplate = DomUtils.parseXmlValidating(s); - -    IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); - -    // replace data -    final Element idlassertion = identityLink.getSamlAssertion(); - -    // - set fake baseID; -    final Node prIdentification = XPathUtils -        .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); -    prIdentification.getFirstChild().setNodeValue(eidData.getPseudonym()); - -    // - set last name -    final Node prFamilyName = XPathUtils -        .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); -    prFamilyName.getFirstChild().setNodeValue(eidData.getFamilyName()); - -    // - set first name -    final Node prGivenName = XPathUtils -        .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); -    prGivenName.getFirstChild().setNodeValue(eidData.getGivenName()); - -    // - set date of birth -    final Node prDateOfBirth = XPathUtils -        .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); - -    prDateOfBirth.getFirstChild().setNodeValue(eidData.getDateOfBirth()); - -    identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink(); - -    String idValue = identityLink.getIdentificationValue(); -    String idType = identityLink.getIdentificationType(); -    String targetId = pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(); -    final Pair<String, String> bpkCalc = BpkBuilder.generateAreaSpecificPersonIdentifier(idValue, idType, targetId); -    return new SzrResultHolder(identityLink, bpkCalc.getFirst()); - -  } -  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java index 6fc6d499..c7843be5 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java @@ -26,9 +26,16 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Component;  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; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; +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.TaskExecutionException;  import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; @@ -46,6 +53,7 @@ import lombok.extern.slf4j.Slf4j;   *   <li>TODO MDS, BPK of new entry</li>   * </ul>   * + * @author tlenz   * @author amarsalek   * @author ckollmann   */ @@ -53,36 +61,40 @@ import lombok.extern.slf4j.Slf4j;  @Component("CreateNewErnbEntryTask")  public class CreateNewErnpEntryTask extends AbstractAuthServletTask { -  //private final SzrClient szrClient; +  private final ErnpRestClient ernpClient; -  ///** -  // * Constructor. -  // * @param szrClient SZR client for creating a new ERnP entry -  // */ -  //public CreateNewErnpEntryTask(SzrClient szrClient) { -  //  this.szrClient = szrClient; -  //} +  /** +   * Constructor. +   * @param client SZR client for creating a new ERnP entry +   */ +  public CreateNewErnpEntryTask(@Autowired ErnpRestClient client) { +    this.ernpClient = client; +  }    @Override    public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)        throws TaskExecutionException {      try { -      //SimpleEidasData simpleEidasData = MatchingTaskUtils.getInitialEidasData(pendingReq);    -           -      // insert person into ERnP -      //TODO: should we insert it directly into ERnP? -      //TODO: has to updated to new eIDAS document model in ERnP -      //String vsz = szrClient.createNewErnpEntry(simpleEidasData); - -      // finish matching process, because new user-entry uniquly matches -      //log.info("User successfully registerred into ERnP and matching tasks are finished "); -      //MatchingTaskUtils.storeFinalMatchingResult(pendingReq,  -      //    MatchedPersonResult.builder() -      //        .vsz(vsz) -      //        .build()); -       -      log.warn("Skipping new insert ERnP task, because it's currently unknown who we should it"); +      SimpleEidasData simpleEidasData = MatchingTaskUtils.getInitialEidasData(pendingReq);             +      if (simpleEidasData == null) { +        throw new WorkflowException("step09", "No initial eIDAS authn data", true); +         +      } +      //add person into ERnP +      ErnpRegisterResult resp = ernpClient.add(simpleEidasData); +      if (resp.getPersonResult().size() != 1) { +        log.error("Receive {} from ERnP during 'add person' step",  +            resp.getPersonResult().isEmpty() ? "no result" : "more-than-one result"); +        throw new WorkflowException("step09", "Add person into ERnP failed", true); +         +      } +            +      // finish matching process, because new user-entry uniquly matches +      log.info("User successfully registerred into ERnP and matching tasks are finished "); +      MatchingTaskUtils.storeFinalMatchingResult(pendingReq,  +          MatchedPersonResult.generateFormMatchingResult( +              resp.getPersonResult().get(0), simpleEidasData.getCitizenCountryCode()));      } catch (final Exception e) {        log.error("Initial search FAILED.", e); diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java index 7107709f..d29519be 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java @@ -79,6 +79,13 @@ public class GenerateOtherLoginMethodGuiTask extends AbstractAuthServletTask {          config.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_UIOPTIONS,              Constants.HTML_FORM_ADVANCED_MATCHING_FAILED, String.valueOf(true)); +        //set detailed error-code +        if (executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON) != null) { +          config.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_UIOPTIONS, +              Constants.HTML_FORM_ADVANCED_MATCHING_FAILED_REASON,  +              executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON).toString()); +        } +                }        guiBuilder.build(request, response, config, "Other login methods selection form"); diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java index f295d66b..3a775837 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java @@ -122,8 +122,9 @@ public class InitialSearchTask extends AbstractAuthServletTask {        if (resultCount == 0) {          step6CountrySpecificSearch(executionContext, searchResult.getOperationStatus(), eidasData); -      } else if (resultCount == 1) { -        foundMatchFinalizeTask(searchResult, eidasData); +      } else if (resultCount == 1) {         +        RegisterResult updatedResult = step3CheckRegisterUpdateNecessary(searchResult, eidasData);         +        foundMatchFinalizeTask(updatedResult, eidasData);        } else {          throw new WorkflowException("step2RegisterSearchWithPersonIdentifier", @@ -146,10 +147,12 @@ public class InitialSearchTask extends AbstractAuthServletTask {      if (searchResult.getResultCount() == 0) {        log.trace("'step6CountrySpecificSearch' ends with no result. Forward to next matching step ... ");        step8RegisterSearchWithMds(executionContext, searchResult.getOperationStatus(), eidasData); +            } else if (searchResult.getResultCount() == 1) {        log.trace("'step6CountrySpecificSearch' finds a person. Forward to 'step7aKittProcess' step ... "); -      registerSearchService.step7aKittProcess(searchResult, eidasData); -      foundMatchFinalizeTask(searchResult, eidasData); +      RegisterStatusResults updatedResult = registerSearchService.step7aKittProcess(searchResult, eidasData); +      foundMatchFinalizeTask(updatedResult.getResult(), eidasData); +            } else {        throw new WorkflowException("step6CountrySpecificSearch",            "More than one entry with unique country-specific information", true); @@ -164,34 +167,36 @@ public class InitialSearchTask extends AbstractAuthServletTask {      if (registerData.getResultCount() == 0) {        log.debug("Matching step: 'step8RegisterSearchWithMds' has no result. Forward to create new ERnP entry ...  ");        executionContext.put(TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK, true); +            } else {        log.debug("Matching step: 'step8RegisterSearchWithMds' has #{} results. "            + "Forward to GUI based matching steps ... ", registerData.getResultCount());        MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerData);        executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +            }    } -  private void foundMatchFinalizeTask(RegisterStatusResults searchResult, SimpleEidasData eidasData) -      throws WorkflowException, EaafStorageException { -    RegisterResult updatedResult = step3CheckRegisterUpdateNecessary(searchResult.getResult(), eidasData); -    MatchedPersonResult result = MatchedPersonResult.generateFormMatchingResult( -        updatedResult, eidasData.getCitizenCountryCode()); -    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, result); -  } - -  private RegisterResult step3CheckRegisterUpdateNecessary(RegisterResult searchResult, -                                                           SimpleEidasData eidasData) { +  private RegisterResult step3CheckRegisterUpdateNecessary( +      RegisterStatusResults searchResult, SimpleEidasData eidasData) throws WorkflowException {      log.trace("Starting step3CheckRegisterUpdateNecessary"); -    if (!eidasData.equalsRegisterData(searchResult)) { -      log.info("Skipping update-register-information step, because it's not supported yet"); -      //TODO: return updated search result if updates are allowed -      return searchResult; +    if (!eidasData.equalsRegisterData(searchResult.getResult())) { +      log.debug("PersonalIdentifier match but MDS or other information changed. Starting update process ... ");         +      return registerSearchService.step7aKittProcess(searchResult, eidasData).getResult(); +            } else {        log.debug("Register information match to eIDAS information. No update required"); -      return searchResult; +      return searchResult.getResult();      }    } +   +  private void foundMatchFinalizeTask(RegisterResult updatedResult, SimpleEidasData eidasData) +      throws WorkflowException, EaafStorageException { +    MatchedPersonResult result =  +        MatchedPersonResult.generateFormMatchingResult(updatedResult, eidasData.getCitizenCountryCode()); +    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, result); +     +  }    @NotNull    private SimpleEidasData convertEidasAttrToSimpleData() diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java index acf469d3..89a3f350 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java @@ -23,16 +23,24 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED; +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON; +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK; +  import java.util.Enumeration;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils;  import org.jetbrains.annotations.NotNull;  import org.springframework.stereotype.Component;  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; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput.AdresssucheOutputBuilder;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException; @@ -43,15 +51,9 @@ 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.EaafStorageException;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; -import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; +import at.gv.egiz.eaaf.core.impl.idp.controller.tasks.AbstractLocaleAuthServletTask;  import lombok.extern.slf4j.Slf4j; -import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED; -import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK; -  /**   * Task receives the response of {@link GenerateAustrianResidenceGuiTask} and handles it. @@ -67,7 +69,7 @@ import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSIT   * </ul>   * Transitions:   * <ul> - *   <li>{@link CreateNewErnpEntryTask} if no results from search with residency data in registers</li> + *   <li>{@link GenerateOtherLoginMethodGuiTask} if no results from search with residency data in registers</li>   *   <li>{@link CreateIdentityLinkTask} if one exact match between initial register search (with MDS) and results   *   from search with residency data in registers exists</li>   *   <li>{@link GenerateOtherLoginMethodGuiTask} if a user input error has happened</li> @@ -79,71 +81,77 @@ import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSIT   */  @Slf4j  @Component("ReceiveAustrianResidenceGuiResponseTask") -public class ReceiveAustrianResidenceGuiResponseTask extends AbstractAuthServletTask { +public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthServletTask { -  public static final String PARAM_FORMER_RESIDENCE_AVAILABLE = "formerResidenceAvailable"; -  public static final String PARAM_STREET = "street"; -  public static final String PARAM_CITY = "city"; -  public static final String PARAM_ZIPCODE = "zipcode"; +  private static final String MSG_PROP_20 = "module.eidasauth.matching.20"; +  private static final String MSG_PROP_21 = "module.eidasauth.matching.21"; +  private static final String MSG_PROP_22 = "module.eidasauth.matching.22"; +   +  public static final String HTTP_PARAM_NO_RESIDENCE = "noResidence";      private final RegisterSearchService registerSearchService;    public ReceiveAustrianResidenceGuiResponseTask(RegisterSearchService registerSearchService) {      this.registerSearchService = registerSearchService; +        } - -  @Data -  @AllArgsConstructor -  @NoArgsConstructor -  public static class UserInput { -    private boolean formerResidenceAvailable; -    private String zipcode; -    private String city; -    private String street; -  } - +      @Override -  public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) -      throws TaskExecutionException { +  protected void executeWithLocale(ExecutionContext executionContext, HttpServletRequest request, +      HttpServletResponse response) throws TaskExecutionException {      log.trace("Starting ReceiveAustrianResidenceGuiResponseTask"); -    UserInput input = parseHtmlInput(request); -    if (!input.isFormerResidenceAvailable()) { -      moveToNextTask(executionContext); -      return; - -    } - -    if (input.getStreet().isEmpty() || input.getCity().isEmpty() || input.getZipcode().isEmpty()) { -      // HTML form should ensure that mandatory fields are set => this should never happen -      executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); -      executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); -      return; - -    } +    try {     +      //return to AuswahlScreen if HTTP_PARAM_NO_RESIDENCE was selected +      final boolean forwardWithOutMandate = parseFlagFromHttpRequest(request, HTTP_PARAM_NO_RESIDENCE, false); +      if (forwardWithOutMandate) { +        log.debug("User selects 'no residence' button. Switch back to 'other matching' selection ... ");        +        executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +       +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_20); +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);                   +        return; +       +      } +             +      //load search parameters from HTML form     +      AdresssucheOutput input = parseHtmlInput(request);         +      if (validateHtmlInput(input)) { +        // HTML form should ensure that mandatory fields are set => this should never happen +        log.warn("HTML form contains no residence information. Switch back to 'other matching' selection ... "); +        executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +     +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_21); +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); +        return; -    try { +      } +     +      // get pre-processed information        SimpleEidasData eidasData = MatchingTaskUtils.getInitialEidasData(pendingReq);        RegisterStatusResults initialSearchResult = MatchingTaskUtils.getIntermediateMatchingResult(pendingReq); +      // search in register        RegisterStatusResults residencyResult = -          registerSearchService.searchWithResidence(initialSearchResult.getOperationStatus(), -              eidasData, input.zipcode, input.city, input.street); -      if (residencyResult.getResultCount() == 0) { -        //TODO: her we should add a GUI step of result is zero to inform user an forward process by click -        moveToNextTask(executionContext); - -      } else if (residencyResult.getResultCount() == 1) { -        compareSearchResultWithInitialData(executionContext, residencyResult, eidasData); +          registerSearchService.searchWithResidence(initialSearchResult.getOperationStatus(), eidasData, input); +       +      // validate matching response from registers +      if (residencyResult.getResultCount() != 1) { +        log.info("Find {} match by using residence information. Forward user to 'other matching' selection ... ", +            residencyResult.getResultCount() == 0 ? "no" : "more-than-one");        +        executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +         +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_22); +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);            } else { -        /*TODO: align with form generation task and to better error handling in case of more-than-one result. -         *      Maybe the user has to provide more information. -         */ -        throw new TaskExecutionException(pendingReq, -            "Manual Fix necessary", new ManualFixNecessaryException(eidasData)); +        log.debug("Find single match by using residence information. Starting data validation ... "); +        compareSearchResultWithInitialData(residencyResult, eidasData);        } +    } catch (WorkflowException e) { +      throw new TaskExecutionException(pendingReq, "Search with residency data failed", e); +            } catch (EaafStorageException e) {        log.error("Search with residency data failed", e);        throw new TaskExecutionException(pendingReq, "Search with residency data failed", e); @@ -151,58 +159,67 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractAuthServlet      }    } -  private void compareSearchResultWithInitialData(ExecutionContext executionContext, -      RegisterStatusResults residencyResult, SimpleEidasData eidasData) +  private boolean validateHtmlInput(AdresssucheOutput input) { +    return StringUtils.isEmpty(input.getMunicipality())  +        && StringUtils.isEmpty(input.getNumber()) +        && StringUtils.isEmpty(input.getPostleitzahl()) +        && StringUtils.isEmpty(input.getStreet()) +        && StringUtils.isEmpty(input.getVillage());             +  } + +  private void compareSearchResultWithInitialData(RegisterStatusResults residencyResult, SimpleEidasData eidasData)        throws TaskExecutionException, EaafStorageException {      try { -      if (eidasData.equalsRegisterData(residencyResult.getResult())) { +      if (!eidasData.equalsRegisterData(residencyResult.getResult())) {          // update register information -        registerSearchService.step7aKittProcess(residencyResult, eidasData); +        RegisterStatusResults updateResult = registerSearchService.step7aKittProcess(residencyResult, eidasData); -        // store search 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.storeFinalMatchingResult(pendingReq,              MatchedPersonResult.generateFormMatchingResult( -                residencyResult.getResult(), eidasData.getCitizenCountryCode())); +                updateResult.getResult(), eidasData.getCitizenCountryCode()));        } else { -        moveToNextTask(executionContext); - +        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.storeFinalMatchingResult(pendingReq, +            MatchedPersonResult.generateFormMatchingResult( +                residencyResult.getResult(), eidasData.getCitizenCountryCode())); +                } - +                  } catch (WorkflowException e) { +      log.warn("Kitt operation after successful residence matching FAILED.", e);        throw new TaskExecutionException(pendingReq, "Search failed", new ManualFixNecessaryException(eidasData));      }    } -  private void moveToNextTask(ExecutionContext executionContext) { -    // Later on, this should transition to Step 20 -    executionContext.put(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK, true); - -  } - -  private @NotNull UserInput parseHtmlInput(HttpServletRequest request) { +  private @NotNull AdresssucheOutput parseHtmlInput(HttpServletRequest request) {      Enumeration<String> reqParamNames = request.getParameterNames(); -    UserInput result = new UserInput(); +    AdresssucheOutputBuilder resultBuilder = AdresssucheOutput.builder();      while (reqParamNames.hasMoreElements()) {        final String paramName = reqParamNames.nextElement();        String escaped = StringEscapeUtils.escapeHtml(request.getParameter(paramName)); -      if (PARAM_FORMER_RESIDENCE_AVAILABLE.equalsIgnoreCase(paramName)) { -        result.setFormerResidenceAvailable(Boolean.parseBoolean(escaped)); +      if (AdresssucheController.PARAM_MUNIPICALITY.equalsIgnoreCase(paramName)) { +        resultBuilder.municipality(escaped); -      } else if (PARAM_STREET.equalsIgnoreCase(paramName)) { -        result.setStreet(escaped); +      } else if (AdresssucheController.PARAM_NUMBER.equalsIgnoreCase(paramName)) { +        resultBuilder.number(escaped); -      } else if (PARAM_CITY.equalsIgnoreCase(paramName)) { -        result.setCity(escaped); +      } else if (AdresssucheController.PARAM_POSTLEITZAHL.equalsIgnoreCase(paramName)) { +        resultBuilder.postleitzahl(escaped); -      } else if (PARAM_ZIPCODE.equalsIgnoreCase(paramName)) { -        result.setZipcode(escaped); +      } else if (AdresssucheController.PARAM_STREET.equalsIgnoreCase(paramName)) { +        resultBuilder.street(escaped); + +      } else if (AdresssucheController.PARAM_VILLAGE.equalsIgnoreCase(paramName)) { +        resultBuilder.village(escaped);        }      } -    return result; - +     +    return resultBuilder.build();        }  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java index 3e57ea24..514e38ba 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java @@ -24,6 +24,7 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;  import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED; +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON;  import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK;  import static at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.IdAustriaClientAuthConstants.MODULE_NAME_FOR_LOGGING; @@ -127,6 +128,9 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet    private static final String ERROR_MSG_02 = "PVP response decryption FAILED. No credential found.";    private static final String ERROR_MSG_03 = "PVP response validation FAILED."; +  private static final String MSG_PROP_23 = "module.eidasauth.matching.23"; +  private static final String MSG_PROP_24 = "module.eidasauth.matching.24"; +      /**     * Creates the new task, with autowired dependencies from Spring.     */ @@ -152,7 +156,9 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet        Pair<PvpSProfileResponse, Boolean> processedMsg = validateAssertion((PvpSProfileResponse) inboundMessage);        if (processedMsg.getSecond()) {          // forward to next matching step in case of ID Autria authentication was stopped by user -        executionContext.put(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK, true); +        executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_23); +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);                        return;        } @@ -171,8 +177,9 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet        // check if MDS from ID Austria authentication matchs to eIDAS authentication        if (!simpleMobileSignatureData.equalsSimpleEidasData(eidasData)) { -        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);          executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_24); +        executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);            return;        } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java index f4419c1c..c9f043b5 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java @@ -23,17 +23,19 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.stereotype.Component; +  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SelectedLoginMethod;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.impl.idp.controller.tasks.AbstractLocaleAuthServletTask;  import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.StringEscapeUtils; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Enumeration;  /**   * Handles user's selection from {@link GenerateOtherLoginMethodGuiTask}. @@ -65,12 +67,13 @@ public class ReceiveOtherLoginMethodGuiResponseTask extends AbstractLocaleAuthSe        SelectedLoginMethod selection = SelectedLoginMethod.valueOf(extractUserSelection(request));        executionContext.put(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER, selection);        executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED); +      executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON);        transitionToNextTask(executionContext, selection);      } catch (final Exception e) {        log.error("Parsing selected login method FAILED.", e);        executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); -      executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); +      executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true);            }    } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml index c9bdad94..6ca21550 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml @@ -35,6 +35,8 @@    <!-- alternative matching modes -->    <pd:Transition  from="generateOtherLoginMethodGuiTask"            to="receiveOtherLoginMethodGuiResponseTask" /> +  <pd:Transition  conditionExpression="ctx['TASK_GenerateOtherLoginMethodGuiTask'] or ctx['changeLanguage']" +                  from="receiveOtherLoginMethodGuiResponseTask"     to="generateOtherLoginMethodGuiTask" />    <pd:Transition  conditionExpression="ctx['TASK_GenerateAlternativeEidasAuthn']"                    from="receiveOtherLoginMethodGuiResponseTask"     to="generateAlternativeEidasAuthnRequest" />    <pd:Transition  conditionExpression="ctx['TASK_GenerateMobilePhoneSignatureRequestTask']" @@ -54,17 +56,17 @@    <!-- ID Austria authentication -->    <pd:Transition  from="generateMobilePhoneSignatureRequestTask"    to="receiveMobilePhoneSignatureResponseTask" /> -  <pd:Transition  conditionExpression="ctx['TASK_GenerateAustrianResidenceGuiTask']" +  <pd:Transition  conditionExpression="ctx['TASK_GenerateOtherLoginMethodGuiTask']"                    from="receiveMobilePhoneSignatureResponseTask"    to="generateOtherLoginMethodGuiTask" />    <pd:Transition  from="receiveMobilePhoneSignatureResponseTask"    to="generateIdentityLink" />    <!-- address searching --> -  <pd:Transition  from="generateAustrianResidenceGuiTask"           to="receiveAustrianResidenceGuiResponseTask" />     +  <pd:Transition  from="generateAustrianResidenceGuiTask"           to="receiveAustrianResidenceGuiResponseTask" />         +  <pd:Transition  conditionExpression="ctx['changeLanguage']" +                  from="receiveAustrianResidenceGuiResponseTask"    to="generateAustrianResidenceGuiTask" />    <pd:Transition  conditionExpression="ctx['TASK_GenerateOtherLoginMethodGuiTask']" -                  from="receiveAustrianResidenceGuiResponseTask"    to="generateOtherLoginMethodGuiTask" />  -  <pd:Transition  conditionExpression="ctx['TASK_CreateNewErnpEntryTask']" -                  from="receiveAustrianResidenceGuiResponseTask"    to="createNewErnpEntryTask" />                                     +                  from="receiveAustrianResidenceGuiResponseTask"    to="generateOtherLoginMethodGuiTask" />       <pd:Transition  from="receiveAustrianResidenceGuiResponseTask"    to="generateIdentityLink" /> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml index d82ccec5..40e63a91 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml @@ -26,13 +26,8 @@    <bean id="zmrAddressClient"          class="at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrAddressSoapClient" /> -  <!-- bean id="ZmrClientForeIDAS" -        class="at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.DummyZmrClient" /--> - - -  <bean id="ErnbClientForeIDAS" -        class="at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.DummyErnpClient" /> - +  <bean id="ernpClient" +        class="at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient" />    <bean id="eIDASAuthModule"      class="at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasAuthenticationModulImpl"> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties index 3ccfff19..3942f30a 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties @@ -20,4 +20,15 @@ module.eidasauth.matching.02=Matching failed, because ZMR response contains hist  module.eidasauth.matching.03=Matching failed in workflow step: {0} with error: {1}  module.eidasauth.matching.04=An error occurred while loading your data from official registers. Please contact the support.   +module.eidasauth.matching.11=Matching failed, because of an ERnP communication error. Reason: {0} +module.eidasauth.matching.12=Matching failed, because ERnP response contains historic information which is not supported. + +module.eidasauth.matching.20=Matching be using residence information was canceled. Use another method for matching or create a new Austrian identity.   +module.eidasauth.matching.21=Matching be using residence information failed by missing input information. Use another method for matching or create a new Austrian identity.  +module.eidasauth.matching.22=Can not find an unique match by using residence information. Provide more or other data, use another method for matching, or create a new Austrian identity. +module.eidasauth.matching.23=Matching be using Austrian Identity was canceled. Use another method for matching or create a new Austrian identity. +module.eidasauth.matching.24=Matching be using Austrian Identity not possible. Use another method for matching or create a new Austrian identity. +module.eidasauth.matching.25=Matching be using alternative eIDAS authentication not possible. Provide more or other data, use another method for matching, or create a new Austrian identity. +  module.eidasauth.matching.99=Matching failed, because of an unexpected processing error. Reason: {0} + diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/wsdl/ernp_client/openapi.json b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/wsdl/ernp_client/openapi.json new file mode 100644 index 00000000..9e09240f --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/wsdl/ernp_client/openapi.json @@ -0,0 +1,1940 @@ +{ +  "openapi" : "3.0.1", +  "info" : { +    "title" : "ERNP", +    "version" : "1.0.0" +  }, +  "servers" : [ { +    "url" : "https://stportal.bmi.intra.gv.at/at.gv.bmi.erpsrv-p/srv/rest/", +    "description" : "Produktion", +    "variables" : { } +  }, { +    "url" : "https://stportal.bmi.intra.gv.at/at.gv.bmi.erpsrv-e/srv/rest/", +    "description" : "Entwicklung", +    "variables" : { } +  }, { +    "url" : "https://stportal.bmi.intra.gv.at/at.gv.bmi.erpsrv-t/srv/rest/", +    "description" : "Interne Test", +    "variables" : { } +  }, { +    "url" : "https://stportal.bmi.intra.gv.at/at.gv.bmi.erpsrv-a/srv/rest/", +    "description" : "Externe Test", +    "variables" : { } +  }, { +    "url" : "https://stportal.bmi.intra.gv.at/at.gv.bmi.erpsrv-b/srv/rest/", +    "description" : "Businespartner Test", +    "variables" : { } +  }, { +    "url" : "http://localhost:29200/at.gv.bmi.erpv01-d/srv/rest/", +    "description" : "Lokal", +    "variables" : { } +  }, { +    "url" : "http://localhost:29200/at.gv.bmi.erpv01-e/srv/rest/", +    "description" : "Entwicklung (kein Portal)", +    "variables" : { } +  }, { +    "url" : "http://localhost:29200/at.gv.bmi.erpv01-t/srv/rest/", +    "description" : "Interne Test (kein Portal)", +    "variables" : { } +  }, { +    "url" : "http://localhost:29200/at.gv.bmi.erpv01-a/srv/rest/", +    "description" : "Externe Test (kein Portal)", +    "variables" : { } +  }, { +    "url" : "http://localhost:29200/at.gv.bmi.erpv11-a/srv/rest/", +    "description" : "Businespartner Test (kein Portal)", +    "variables" : { } +  } ], +  "paths" : { +    "/eidas/person/aendern" : { +      "post" : { +        "operationId" : "aendern", +        "parameters" : [ { +          "name" : "Client-Request-Time", +          "in" : "header", +          "description" : "Client-Requestzeit im ISO-8601 Format mit optionaler Zeitzone (zb '2016-10-27T16:36:08.993')", +          "schema" : { +            "type" : "string", +            "format" : "date-time" +          } +        }, { +          "name" : "Client-Request-Id", +          "in" : "header", +          "description" : "Client-Request ID (um Systemübergreifende Fehlersuche zu vereinfache)", +          "schema" : { +            "type" : "string" +          } +        }, { +          "name" : "Client-Behkz", +          "in" : "header", +          "description" : "Client-Behördenkennzeichen", +          "required" : true, +          "schema" : { +            "type" : "string" +          } +        }, { +          "name" : "Client-Name", +          "in" : "header", +          "description" : "Client-Name bzw Applikationskürzel und Version des aufrufenden Systems (zb 'ZMR 3.4.5')", +          "required" : true, +          "schema" : { +            "type" : "string" +          } +        } ], +        "requestBody" : { +          "content" : { +            "application/json" : { +              "schema" : { +                "$ref" : "#/components/schemas/PersonAendern" +              } +            }, +            "application/xml" : { +              "schema" : { +                "$ref" : "#/components/schemas/PersonAendern" +              } +            } +          } +        }, +        "responses" : { +          "default" : { +            "description" : "Erfolgreicher Response hat Status 200 wenn Responsepayload vorhanden, sonst 204", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/AendernResponse" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/AendernResponse" +                } +              } +            } +          }, +          "4XX" : { +            "description" : "Client Fehler (kann vom Client behoben werden)", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              } +            } +          }, +          "5XX" : { +            "description" : "Server Fehler (normalerweise nicht vom Client behebbar)", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              } +            } +          } +        } +      } +    }, +    "/eidas/person/anlegen" : { +      "post" : { +        "operationId" : "anlegen", +        "parameters" : [ { +          "name" : "Client-Request-Time", +          "in" : "header", +          "description" : "Client-Requestzeit im ISO-8601 Format mit optionaler Zeitzone (zb '2016-10-27T16:36:08.993')", +          "schema" : { +            "type" : "string", +            "format" : "date-time" +          } +        }, { +          "name" : "Client-Request-Id", +          "in" : "header", +          "description" : "Client-Request ID (um Systemübergreifende Fehlersuche zu vereinfache)", +          "schema" : { +            "type" : "string" +          } +        }, { +          "name" : "Client-Behkz", +          "in" : "header", +          "description" : "Client-Behördenkennzeichen", +          "required" : true, +          "schema" : { +            "type" : "string" +          } +        }, { +          "name" : "Client-Name", +          "in" : "header", +          "description" : "Client-Name bzw Applikationskürzel und Version des aufrufenden Systems (zb 'ZMR 3.4.5')", +          "required" : true, +          "schema" : { +            "type" : "string" +          } +        } ], +        "requestBody" : { +          "content" : { +            "application/json" : { +              "schema" : { +                "$ref" : "#/components/schemas/PersonAnlegen" +              } +            }, +            "application/xml" : { +              "schema" : { +                "$ref" : "#/components/schemas/PersonAnlegen" +              } +            } +          } +        }, +        "responses" : { +          "default" : { +            "description" : "Erfolgreicher Response hat Status 200 wenn Responsepayload vorhanden, sonst 204", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/AnlegenResponse" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/AnlegenResponse" +                } +              } +            } +          }, +          "4XX" : { +            "description" : "Client Fehler (kann vom Client behoben werden)", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              } +            } +          }, +          "5XX" : { +            "description" : "Server Fehler (normalerweise nicht vom Client behebbar)", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              } +            } +          } +        } +      } +    }, +    "/eidas/person/suchen" : { +      "post" : { +        "operationId" : "suchen", +        "parameters" : [ { +          "name" : "Client-Request-Time", +          "in" : "header", +          "description" : "Client-Requestzeit im ISO-8601 Format mit optionaler Zeitzone (zb '2016-10-27T16:36:08.993')", +          "schema" : { +            "type" : "string", +            "format" : "date-time" +          } +        }, { +          "name" : "Client-Request-Id", +          "in" : "header", +          "description" : "Client-Request ID (um Systemübergreifende Fehlersuche zu vereinfache)", +          "schema" : { +            "type" : "string" +          } +        }, { +          "name" : "Client-Behkz", +          "in" : "header", +          "description" : "Client-Behördenkennzeichen", +          "required" : true, +          "schema" : { +            "type" : "string" +          } +        }, { +          "name" : "Client-Name", +          "in" : "header", +          "description" : "Client-Name bzw Applikationskürzel und Version des aufrufenden Systems (zb 'ZMR 3.4.5')", +          "required" : true, +          "schema" : { +            "type" : "string" +          } +        } ], +        "requestBody" : { +          "content" : { +            "application/json" : { +              "schema" : { +                "$ref" : "#/components/schemas/PersonSuchen" +              } +            }, +            "application/xml" : { +              "schema" : { +                "$ref" : "#/components/schemas/PersonSuchen" +              } +            } +          } +        }, +        "responses" : { +          "default" : { +            "description" : "Erfolgreicher Response hat Status 200 wenn Responsepayload vorhanden, sonst 204", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/SuchenResponse" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/SuchenResponse" +                } +              } +            } +          }, +          "4XX" : { +            "description" : "Client Fehler (kann vom Client behoben werden)", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              } +            } +          }, +          "5XX" : { +            "description" : "Server Fehler (normalerweise nicht vom Client behebbar)", +            "content" : { +              "application/json" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              }, +              "application/xml" : { +                "schema" : { +                  "$ref" : "#/components/schemas/Fault" +                } +              } +            } +          } +        } +      } +    } +  }, +  "components" : { +    "schemas" : { +      "Fault" : { +        "required" : [ "message" ], +        "type" : "object", +        "properties" : { +          "message" : { +            "type" : "string", +            "xml" : { +              "name" : "Message" +            } +          }, +          "faultDetails" : { +            "$ref" : "#/components/schemas/FaultDetails" +          } +        }, +        "xml" : { +          "name" : "Fault" +        } +      }, +      "FaultDetails" : { +        "required" : [ "fault" ], +        "type" : "object", +        "properties" : { +          "faultNumber" : { +            "type" : "integer", +            "format" : "int32", +            "xml" : { +              "name" : "FaultNumber" +            } +          }, +          "fault" : { +            "type" : "array", +            "xml" : { +              "name" : "Fault" +            }, +            "items" : { +              "$ref" : "#/components/schemas/FaultDetailsEntry" +            } +          } +        } +      }, +      "FaultDetailsEntry" : { +        "type" : "object", +        "properties" : { +          "key" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "message" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          } +        } +      }, +      "AendernResponse" : { +        "required" : [ "person" ], +        "type" : "object", +        "properties" : { +          "person" : { +            "$ref" : "#/components/schemas/Person" +          } +        }, +        "xml" : { +          "name" : "AendernResponse" +        } +      }, +      "AkademischerGrad" : { +        "required" : [ "ebene", "kurzerName", "langerName", "stellung" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "ausgestelltVon" : { +            "$ref" : "#/components/schemas/AusgestelltVon" +          }, +          "ebene" : { +            "type" : "string", +            "xml" : { +              "name" : "Ebene" +            }, +            "enum" : [ "0", "1", "2", "2/3", "3" ] +          }, +          "stellung" : { +            "type" : "string", +            "xml" : { +              "name" : "Stellung" +            }, +            "enum" : [ "Vorangestellt", "Nachgestellt" ] +          }, +          "langerName" : { +            "type" : "string", +            "xml" : { +              "name" : "LangerName" +            } +          }, +          "kurzerName" : { +            "type" : "string", +            "xml" : { +              "name" : "KurzerName" +            } +          } +        } +      }, +      "Anschrift" : { +        "required" : [ "staat", "strasse", "type" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "staat" : { +            "$ref" : "#/components/schemas/Staat" +          }, +          "gemeinde" : { +            "type" : "string", +            "xml" : { +              "name" : "Gemeinde" +            } +          }, +          "strasse" : { +            "type" : "string", +            "xml" : { +              "name" : "Strasse" +            } +          }, +          "postleitzahl" : { +            "type" : "string", +            "xml" : { +              "name" : "Postleitzahl" +            } +          }, +          "hausnummer" : { +            "type" : "string", +            "xml" : { +              "name" : "Hausnummer" +            } +          }, +          "adresszusatz" : { +            "type" : "string", +            "xml" : { +              "name" : "Adresszusatz" +            } +          }, +          "stiege" : { +            "type" : "string", +            "xml" : { +              "name" : "Stiege" +            } +          }, +          "tuer" : { +            "type" : "string", +            "xml" : { +              "name" : "Tuer" +            } +          }, +          "kontaktinformationen" : { +            "$ref" : "#/components/schemas/Kontaktinformationen" +          }, +          "type" : { +            "type" : "string" +          } +        }, +        "discriminator" : { +          "propertyName" : "type" +        } +      }, +      "AnschriftInland" : { +        "required" : [ "gemeinde", "hausnummer", "ort", "postleitzahl", "staat", "strasse" ], +        "type" : "object", +        "allOf" : [ { +          "$ref" : "#/components/schemas/Anschrift" +        }, { +          "type" : "object", +          "properties" : { +            "adressstatus" : { +              "type" : "string", +              "xml" : { +                "name" : "Adressstatus" +              } +            }, +            "ort" : { +              "type" : "string", +              "xml" : { +                "name" : "Ort" +              } +            }, +            "ortZweisprachig" : { +              "type" : "string", +              "xml" : { +                "name" : "OrtZweisprachig" +              } +            }, +            "postort" : { +              "type" : "string", +              "xml" : { +                "name" : "Postort" +              } +            }, +            "codes" : { +              "$ref" : "#/components/schemas/Anschriftcodes" +            }, +            "auskunftssperre" : { +              "type" : "boolean", +              "xml" : { +                "name" : "Auskunftssperre" +              } +            }, +            "wohnsitzqualitaet" : { +              "type" : "string", +              "xml" : { +                "name" : "Wohnsitzqualitaet" +              }, +              "enum" : [ "H", "N", "O" ] +            } +          } +        } ] +      }, +      "AnschriftInlandAgs" : { +        "required" : [ "gemeinde", "hausnummer", "ort", "postleitzahl", "staat", "strasse" ], +        "type" : "object", +        "allOf" : [ { +          "$ref" : "#/components/schemas/Anschrift" +        }, { +          "type" : "object", +          "properties" : { +            "adressstatus" : { +              "type" : "string", +              "xml" : { +                "name" : "Adressstatus" +              } +            }, +            "ort" : { +              "type" : "string", +              "xml" : { +                "name" : "Ort" +              } +            }, +            "ortZweisprachig" : { +              "type" : "string", +              "xml" : { +                "name" : "OrtZweisprachig" +              } +            }, +            "postort" : { +              "type" : "string", +              "xml" : { +                "name" : "Postort" +              } +            }, +            "codes" : { +              "$ref" : "#/components/schemas/Anschriftcodes" +            }, +            "auskunftssperre" : { +              "type" : "boolean", +              "xml" : { +                "name" : "Auskunftssperre" +              } +            }, +            "wohnsitzqualitaet" : { +              "type" : "string", +              "xml" : { +                "name" : "Wohnsitzqualitaet" +              }, +              "enum" : [ "H", "N", "O" ] +            }, +            "detailgrad" : { +              "type" : "string", +              "xml" : { +                "name" : "Detailgrad" +              } +            }, +            "nutzungsartCode" : { +              "type" : "string", +              "xml" : { +                "name" : "NutzungsartCode" +              } +            }, +            "gebaeudeeigenschaft" : { +              "type" : "string", +              "xml" : { +                "name" : "Gebaeudeeigenschaft" +              } +            } +          } +        } ] +      }, +      "Anschriftcodes" : { +        "type" : "object", +        "properties" : { +          "adresscode" : { +            "type" : "string", +            "xml" : { +              "name" : "Adresscode", +              "attribute" : true +            } +          }, +          "subcode" : { +            "type" : "string", +            "xml" : { +              "name" : "Subcode", +              "attribute" : true +            } +          }, +          "ortskennziffer" : { +            "type" : "string", +            "xml" : { +              "name" : "Ortskennziffer", +              "attribute" : true +            } +          }, +          "strassenkennziffer" : { +            "type" : "string", +            "xml" : { +              "name" : "Strassenkennziffer", +              "attribute" : true +            } +          }, +          "objektnummer" : { +            "type" : "string", +            "xml" : { +              "name" : "Objektnummer", +              "attribute" : true +            } +          }, +          "nutzungseinheitlaufnummer" : { +            "type" : "string", +            "xml" : { +              "name" : "Nutzungseinheitlaufnummer", +              "attribute" : true +            } +          }, +          "adrRefkey" : { +            "type" : "string", +            "xml" : { +              "name" : "AdrRefkey", +              "attribute" : true +            } +          }, +          "gbrRefkey" : { +            "type" : "string", +            "xml" : { +              "name" : "GbrRefkey", +              "attribute" : true +            } +          }, +          "gemeindekennziffer" : { +            "type" : "string", +            "xml" : { +              "name" : "Gemeindekennziffer", +              "attribute" : true +            } +          } +        } +      }, +      "AusgestelltVon" : { +        "required" : [ "behoerde", "datum", "staat" ], +        "type" : "object", +        "properties" : { +          "datum" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "name" : "Datum" +            } +          }, +          "behoerde" : { +            "type" : "string", +            "xml" : { +              "name" : "Behoerde" +            } +          }, +          "staat" : { +            "$ref" : "#/components/schemas/Staat" +          } +        } +      }, +      "Benutzer" : { +        "required" : [ "benutzer" ], +        "type" : "object", +        "properties" : { +          "benutzer" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "behoerdenkennzeichen" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          } +        } +      }, +      "Eidas" : { +        "required" : [ "art", "staatscode2", "wert" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "art" : { +            "type" : "string", +            "xml" : { +              "name" : "Art" +            } +          }, +          "wert" : { +            "type" : "string", +            "xml" : { +              "name" : "Wert" +            } +          }, +          "ausstellDatum" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "name" : "AusstellDatum" +            } +          }, +          "ablaufDatum" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "name" : "AblaufDatum" +            } +          }, +          "ausstellBehoerde" : { +            "type" : "string", +            "xml" : { +              "name" : "AusstellBehoerde" +            } +          }, +          "staatscode2" : { +            "type" : "string", +            "xml" : { +              "name" : "Staatscode2" +            } +          } +        } +      }, +      "Kontaktinformationen" : { +        "type" : "object", +        "properties" : { +          "firmenname1" : { +            "type" : "string", +            "xml" : { +              "name" : "Firmenname1" +            } +          }, +          "firmenname2" : { +            "type" : "string", +            "xml" : { +              "name" : "Firmenname2" +            } +          }, +          "ansprechpartner" : { +            "type" : "string", +            "xml" : { +              "name" : "Ansprechpartner" +            } +          }, +          "telefon" : { +            "type" : "string", +            "xml" : { +              "name" : "Telefon" +            } +          }, +          "mobil" : { +            "type" : "string", +            "xml" : { +              "name" : "Mobil" +            } +          }, +          "fax" : { +            "type" : "string", +            "xml" : { +              "name" : "Fax" +            } +          }, +          "email" : { +            "type" : "string", +            "xml" : { +              "name" : "Email" +            } +          }, +          "postfach" : { +            "type" : "string", +            "xml" : { +              "name" : "Postfach" +            } +          } +        } +      }, +      "LetzteOperation" : { +        "required" : [ "begruendung", "durchgefuehrtVon" ], +        "type" : "object", +        "properties" : { +          "begruendung" : { +            "type" : "string", +            "xml" : { +              "name" : "Begruendung" +            } +          }, +          "durchgefuehrtVon" : { +            "$ref" : "#/components/schemas/Benutzer" +          }, +          "vorgang" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "zeitpunkt" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          } +        } +      }, +      "PartialDate" : { +        "required" : [ "jahr" ], +        "type" : "object", +        "properties" : { +          "jahr" : { +            "type" : "integer", +            "format" : "int32", +            "xml" : { +              "attribute" : true +            } +          }, +          "monat" : { +            "type" : "integer", +            "format" : "int32", +            "xml" : { +              "attribute" : true +            } +          }, +          "tag" : { +            "type" : "integer", +            "format" : "int32", +            "xml" : { +              "attribute" : true +            } +          } +        } +      }, +      "Person" : { +        "required" : [ "letzteOperation", "personendaten", "type" ], +        "type" : "object", +        "properties" : { +          "letzteOperation" : { +            "$ref" : "#/components/schemas/LetzteOperation" +          }, +          "personendaten" : { +            "$ref" : "#/components/schemas/PersonendatenErgebnis" +          }, +          "anschrift" : { +            "$ref" : "#/components/schemas/Anschrift" +          }, +          "akademischerGrad" : { +            "type" : "array", +            "xml" : { +              "name" : "AkademischerGrad" +            }, +            "items" : { +              "$ref" : "#/components/schemas/AkademischerGrad" +            } +          }, +          "reisedokument" : { +            "type" : "array", +            "xml" : { +              "name" : "Reisedokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Reisedokument" +            } +          }, +          "sonstigesDokument" : { +            "type" : "array", +            "xml" : { +              "name" : "SonstigesDokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/SonstigesDokument" +            } +          }, +          "staatsangehoerigkeit" : { +            "type" : "array", +            "xml" : { +              "name" : "Staatsangehoerigkeit" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Staatsangehoerigkeit" +            } +          }, +          "eidas" : { +            "type" : "array", +            "xml" : { +              "name" : "Eidas" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Eidas" +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "version" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "type" : { +            "type" : "string" +          } +        }, +        "discriminator" : { +          "propertyName" : "type" +        } +      }, +      "PersonendatenErgebnis" : { +        "required" : [ "basiszahl", "familienname", "geburtsdatum", "vorname" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "familienname" : { +            "type" : "string", +            "xml" : { +              "name" : "Familienname" +            } +          }, +          "nameVorEhe" : { +            "type" : "string", +            "xml" : { +              "name" : "NameVorEhe" +            } +          }, +          "vorname" : { +            "type" : "string", +            "xml" : { +              "name" : "Vorname" +            } +          }, +          "geburtsbundesland" : { +            "type" : "string", +            "xml" : { +              "name" : "Geburtsbundesland" +            }, +            "enum" : [ "Burgenland", "Kärnten", "Niederösterreich", "Oberösterreich", "Salzburg", "Steiermark", "Tirol", "Vorarlberg", "Wien" ] +          }, +          "geburtsort" : { +            "type" : "string", +            "xml" : { +              "name" : "Geburtsort" +            } +          }, +          "geburtsstaat" : { +            "$ref" : "#/components/schemas/Staat" +          }, +          "geburtsdatum" : { +            "$ref" : "#/components/schemas/PartialDate" +          }, +          "geschlecht" : { +            "type" : "string", +            "xml" : { +              "name" : "Geschlecht" +            }, +            "enum" : [ "Männlich", "Weiblich" ] +          }, +          "basiszahl" : { +            "type" : "string", +            "xml" : { +              "name" : "Basiszahl" +            } +          }, +          "kitquelle" : { +            "type" : "string", +            "xml" : { +              "name" : "Kitquelle" +            } +          }, +          "bpkZp" : { +            "type" : "string", +            "xml" : { +              "name" : "BpkZp" +            } +          }, +          "sterbedatum" : { +            "$ref" : "#/components/schemas/PartialDate" +          }, +          "geprueft" : { +            "type" : "boolean", +            "xml" : { +              "name" : "Geprueft" +            } +          } +        } +      }, +      "Reisedokument" : { +        "required" : [ "art" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "ausgestelltVon" : { +            "$ref" : "#/components/schemas/AusgestelltVon" +          }, +          "art" : { +            "type" : "string", +            "xml" : { +              "name" : "Art" +            }, +            "enum" : [ "Asylwerber", "Dienstpass", "Elektronisch", "Fremdenpass", "Konventionspass", "Personalausweis", "Reisepass", "Staatenlos", "Sonstiges" ] +          }, +          "nummer" : { +            "type" : "string", +            "xml" : { +              "name" : "Nummer" +            } +          } +        } +      }, +      "SonstigesDokument" : { +        "required" : [ "art", "nummer" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "ausgestelltVon" : { +            "$ref" : "#/components/schemas/AusgestelltVon" +          }, +          "art" : { +            "type" : "string", +            "xml" : { +              "name" : "Art" +            }, +            "enum" : [ "Führerschein", "Geburtsurkunde", "Heiratsurkunde", "Sonstiges", "Staatsbürgerschaftsnachweis", "Sterbeurkunde", "Todeserklärung" ] +          }, +          "lichtbildausweis" : { +            "type" : "boolean", +            "xml" : { +              "name" : "Lichtbildausweis" +            } +          }, +          "nummer" : { +            "type" : "string", +            "xml" : { +              "name" : "Nummer" +            } +          }, +          "name" : { +            "type" : "string", +            "xml" : { +              "name" : "Name" +            } +          } +        } +      }, +      "Staat" : { +        "type" : "object", +        "properties" : { +          "isoCode3" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "name" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          } +        } +      }, +      "Staatsangehoerigkeit" : { +        "required" : [ "staat" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "staat" : { +            "$ref" : "#/components/schemas/Staat" +          } +        } +      }, +      "ZmrPerson" : { +        "required" : [ "letzteOperation", "personendaten", "qkz" ], +        "type" : "object", +        "allOf" : [ { +          "$ref" : "#/components/schemas/Person" +        }, { +          "type" : "object", +          "properties" : { +            "auskunftssperre" : { +              "type" : "boolean", +              "xml" : { +                "name" : "Auskunftssperre" +              } +            }, +            "qkz" : { +              "type" : "array", +              "xml" : { +                "name" : "Qkz" +              }, +              "items" : { +                "type" : "string" +              } +            } +          } +        } ] +      }, +      "Aendern" : { +        "type" : "object", +        "properties" : { +          "personendaten" : { +            "$ref" : "#/components/schemas/Personendaten" +          }, +          "anschrift" : { +            "$ref" : "#/components/schemas/Anschrift" +          }, +          "akademischerGrad" : { +            "type" : "array", +            "xml" : { +              "name" : "AkademischerGrad" +            }, +            "items" : { +              "$ref" : "#/components/schemas/AkademischerGrad" +            } +          }, +          "reisedokument" : { +            "type" : "array", +            "xml" : { +              "name" : "Reisedokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Reisedokument" +            } +          }, +          "sonstigesDokument" : { +            "type" : "array", +            "xml" : { +              "name" : "SonstigesDokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/SonstigesDokument" +            } +          }, +          "staatsangehoerigkeit" : { +            "type" : "array", +            "xml" : { +              "name" : "Staatsangehoerigkeit" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Staatsangehoerigkeit" +            } +          }, +          "eidas" : { +            "type" : "array", +            "xml" : { +              "name" : "Eidas" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Eidas" +            } +          } +        } +      }, +      "Anlegen" : { +        "type" : "object", +        "properties" : { +          "anschrift" : { +            "$ref" : "#/components/schemas/Anschrift" +          }, +          "akademischerGrad" : { +            "type" : "array", +            "xml" : { +              "name" : "AkademischerGrad" +            }, +            "items" : { +              "$ref" : "#/components/schemas/AkademischerGrad" +            } +          }, +          "reisedokument" : { +            "type" : "array", +            "xml" : { +              "name" : "Reisedokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Reisedokument" +            } +          }, +          "sonstigesDokument" : { +            "type" : "array", +            "xml" : { +              "name" : "SonstigesDokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/SonstigesDokument" +            } +          }, +          "staatsangehoerigkeit" : { +            "type" : "array", +            "xml" : { +              "name" : "Staatsangehoerigkeit" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Staatsangehoerigkeit" +            } +          }, +          "eidas" : { +            "type" : "array", +            "xml" : { +              "name" : "Eidas" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Eidas" +            } +          } +        } +      }, +      "Beenden" : { +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "array", +            "xml" : { +              "name" : "EntityId" +            }, +            "items" : { +              "type" : "string", +              "xml" : { +                "name" : "EntityId" +              } +            } +          } +        } +      }, +      "PersonAendern" : { +        "required" : [ "begruendung", "entityId", "version" ], +        "type" : "object", +        "properties" : { +          "begruendung" : { +            "type" : "string", +            "xml" : { +              "name" : "Begruendung" +            } +          }, +          "anlegen" : { +            "$ref" : "#/components/schemas/Anlegen" +          }, +          "aendern" : { +            "$ref" : "#/components/schemas/Aendern" +          }, +          "beenden" : { +            "$ref" : "#/components/schemas/Beenden" +          }, +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "version" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          } +        }, +        "xml" : { +          "name" : "PersonAendern" +        } +      }, +      "Personendaten" : { +        "required" : [ "familienname", "geburtsdatum", "vorname" ], +        "type" : "object", +        "properties" : { +          "entityId" : { +            "type" : "string", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigAb" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "gueltigBis" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "attribute" : true +            } +          }, +          "familienname" : { +            "type" : "string", +            "xml" : { +              "name" : "Familienname" +            } +          }, +          "nameVorEhe" : { +            "type" : "string", +            "xml" : { +              "name" : "NameVorEhe" +            } +          }, +          "vorname" : { +            "type" : "string", +            "xml" : { +              "name" : "Vorname" +            } +          }, +          "geburtsbundesland" : { +            "type" : "string", +            "xml" : { +              "name" : "Geburtsbundesland" +            }, +            "enum" : [ "Burgenland", "Kärnten", "Niederösterreich", "Oberösterreich", "Salzburg", "Steiermark", "Tirol", "Vorarlberg", "Wien" ] +          }, +          "geburtsort" : { +            "type" : "string", +            "xml" : { +              "name" : "Geburtsort" +            } +          }, +          "geburtsstaat" : { +            "$ref" : "#/components/schemas/Staat" +          }, +          "geburtsdatum" : { +            "$ref" : "#/components/schemas/PartialDate" +          }, +          "geschlecht" : { +            "type" : "string", +            "xml" : { +              "name" : "Geschlecht" +            }, +            "enum" : [ "Männlich", "Weiblich" ] +          } +        } +      }, +      "AnlegenResponse" : { +        "required" : [ "person" ], +        "type" : "object", +        "properties" : { +          "person" : { +            "$ref" : "#/components/schemas/Person" +          } +        }, +        "xml" : { +          "name" : "AnlegenResponse" +        } +      }, +      "PersonAnlegen" : { +        "required" : [ "anschrift", "begruendung", "personendaten" ], +        "type" : "object", +        "properties" : { +          "begruendung" : { +            "type" : "string", +            "xml" : { +              "name" : "Begruendung" +            } +          }, +          "personendaten" : { +            "$ref" : "#/components/schemas/Personendaten" +          }, +          "anschrift" : { +            "$ref" : "#/components/schemas/Anschrift" +          }, +          "akademischerGrad" : { +            "type" : "array", +            "xml" : { +              "name" : "AkademischerGrad" +            }, +            "items" : { +              "$ref" : "#/components/schemas/AkademischerGrad" +            } +          }, +          "reisedokument" : { +            "type" : "array", +            "xml" : { +              "name" : "Reisedokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Reisedokument" +            } +          }, +          "sonstigesDokument" : { +            "type" : "array", +            "xml" : { +              "name" : "SonstigesDokument" +            }, +            "items" : { +              "$ref" : "#/components/schemas/SonstigesDokument" +            } +          }, +          "staatsangehoerigkeit" : { +            "type" : "array", +            "xml" : { +              "name" : "Staatsangehoerigkeit" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Staatsangehoerigkeit" +            } +          }, +          "eidas" : { +            "type" : "array", +            "xml" : { +              "name" : "Eidas" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Eidas" +            } +          } +        }, +        "xml" : { +          "name" : "PersonAnlegen" +        } +      }, +      "SuchenResponse" : { +        "type" : "object", +        "properties" : { +          "person" : { +            "type" : "array", +            "xml" : { +              "name" : "Person" +            }, +            "items" : { +              "$ref" : "#/components/schemas/Person" +            } +          } +        }, +        "xml" : { +          "name" : "SuchenResponse" +        } +      }, +      "PersonSuchen" : { +        "required" : [ "begruendung", "suchdaten", "suchoptionen" ], +        "type" : "object", +        "properties" : { +          "begruendung" : { +            "type" : "string", +            "xml" : { +              "name" : "Begruendung" +            } +          }, +          "suchoptionen" : { +            "$ref" : "#/components/schemas/Suchoptionen" +          }, +          "suchdaten" : { +            "$ref" : "#/components/schemas/Suchdaten" +          } +        }, +        "xml" : { +          "name" : "PersonSuchen" +        } +      }, +      "SuchAnschrift" : { +        "type" : "object", +        "properties" : { +          "staat" : { +            "$ref" : "#/components/schemas/Staat" +          }, +          "gemeinde" : { +            "type" : "string", +            "xml" : { +              "name" : "Gemeinde" +            } +          }, +          "strasse" : { +            "type" : "string", +            "xml" : { +              "name" : "Strasse" +            } +          }, +          "ort" : { +            "type" : "string", +            "xml" : { +              "name" : "Ort" +            } +          }, +          "postleitzahl" : { +            "type" : "string", +            "xml" : { +              "name" : "Postleitzahl" +            } +          }, +          "hausnummer" : { +            "type" : "string", +            "xml" : { +              "name" : "Hausnummer" +            } +          }, +          "adresszusatz" : { +            "type" : "string", +            "xml" : { +              "name" : "Adresszusatz" +            } +          }, +          "stiege" : { +            "type" : "string", +            "xml" : { +              "name" : "Stiege" +            } +          }, +          "tuer" : { +            "type" : "string", +            "xml" : { +              "name" : "Tuer" +            } +          }, +          "postfach" : { +            "type" : "string", +            "xml" : { +              "name" : "Postfach" +            } +          } +        } +      }, +      "SuchAusgestelltVon" : { +        "type" : "object", +        "properties" : { +          "datum" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "name" : "Datum" +            } +          }, +          "behoerde" : { +            "type" : "string", +            "xml" : { +              "name" : "Behoerde" +            } +          }, +          "staat" : { +            "$ref" : "#/components/schemas/Staat" +          } +        } +      }, +      "SuchEidas" : { +        "type" : "object", +        "properties" : { +          "art" : { +            "type" : "string", +            "xml" : { +              "name" : "Art" +            } +          }, +          "wert" : { +            "type" : "string", +            "xml" : { +              "name" : "Wert" +            } +          }, +          "ausstellDatum" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "name" : "AusstellDatum" +            } +          }, +          "ablaufDatum" : { +            "type" : "string", +            "format" : "date-time", +            "xml" : { +              "name" : "AblaufDatum" +            } +          }, +          "ausstellBehoerde" : { +            "type" : "string", +            "xml" : { +              "name" : "AusstellBehoerde" +            } +          }, +          "staatscode2" : { +            "type" : "string", +            "xml" : { +              "name" : "Staatscode2" +            } +          } +        } +      }, +      "SuchReisedokument" : { +        "type" : "object", +        "properties" : { +          "art" : { +            "type" : "string", +            "xml" : { +              "name" : "Art" +            }, +            "enum" : [ "Asylwerber", "Dienstpass", "Elektronisch", "Fremdenpass", "Konventionspass", "Personalausweis", "Reisepass", "Staatenlos", "Sonstiges" ] +          }, +          "ausgestelltVon" : { +            "$ref" : "#/components/schemas/SuchAusgestelltVon" +          }, +          "nummer" : { +            "type" : "string", +            "xml" : { +              "name" : "Nummer" +            } +          } +        } +      }, +      "SuchStaatsangehoerigkeit" : { +        "type" : "object", +        "properties" : { +          "staat" : { +            "$ref" : "#/components/schemas/Staat" +          } +        } +      }, +      "Suchdaten" : { +        "required" : [ "familienname", "vorname" ], +        "type" : "object", +        "properties" : { +          "basiszahl" : { +            "type" : "string", +            "xml" : { +              "name" : "Basiszahl" +            } +          }, +          "bpkZp" : { +            "type" : "string", +            "xml" : { +              "name" : "BpkZp" +            } +          }, +          "fremdBpkBmiZp" : { +            "type" : "string", +            "xml" : { +              "name" : "FremdBpkBmiZp" +            } +          }, +          "entityId" : { +            "type" : "string", +            "xml" : { +              "name" : "EntityId" +            } +          }, +          "familienname" : { +            "type" : "string", +            "xml" : { +              "name" : "Familienname" +            } +          }, +          "nameVorEhe" : { +            "type" : "string", +            "xml" : { +              "name" : "NameVorEhe" +            } +          }, +          "vorname" : { +            "type" : "string", +            "xml" : { +              "name" : "Vorname" +            } +          }, +          "geburtsdatum" : { +            "$ref" : "#/components/schemas/PartialDate" +          }, +          "geburtsort" : { +            "type" : "string", +            "xml" : { +              "name" : "Geburtsort" +            } +          }, +          "geburtsstaat" : { +            "$ref" : "#/components/schemas/Staat" +          }, +          "geschlecht" : { +            "type" : "string", +            "xml" : { +              "name" : "Geschlecht" +            }, +            "enum" : [ "Männlich", "Weiblich" ] +          }, +          "anschrift" : { +            "$ref" : "#/components/schemas/SuchAnschrift" +          }, +          "reisedokument" : { +            "$ref" : "#/components/schemas/SuchReisedokument" +          }, +          "staatsangehoerigkeit" : { +            "$ref" : "#/components/schemas/SuchStaatsangehoerigkeit" +          }, +          "eidas" : { +            "type" : "array", +            "xml" : { +              "name" : "Eidas" +            }, +            "items" : { +              "$ref" : "#/components/schemas/SuchEidas" +            } +          } +        } +      }, +      "Suchoptionen" : { +        "required" : [ "historisch" ], +        "type" : "object", +        "properties" : { +          "historisch" : { +            "type" : "string", +            "xml" : { +              "name" : "Historisch" +            }, +            "enum" : [ "Aktuell", "AktuellDannHistorisch", "AktuellUndHistorisch" ] +          }, +          "formalisiert" : { +            "type" : "boolean", +            "xml" : { +              "name" : "Formalisiert" +            } +          }, +          "sucheMitNamensteilen" : { +            "type" : "boolean", +            "xml" : { +              "name" : "SucheMitNamensteilen" +            } +          }, +          "suchwizard" : { +            "type" : "boolean", +            "xml" : { +              "name" : "Suchwizard" +            } +          }, +          "zmr" : { +            "type" : "boolean", +            "xml" : { +              "name" : "Zmr" +            } +          } +        }, +        "xml" : { +          "name" : "Suchoptionen", +          "namespace" : "http://bmi.gv.at/ernp" +        } +      } +    } +  } +}
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientProductionTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientProductionTest.java new file mode 100644 index 00000000..66a426a1 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientProductionTest.java @@ -0,0 +1,460 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.clients; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.IfProfileValue; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient; +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.exception.EidasSAuthenticationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.DeSpecificDetailSearchProcessor; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; +import lombok.SneakyThrows; + +@IfProfileValue(name = "spring.profiles.active", value = "devEnvironment") +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { +    "/SpringTest-context_tasks_test.xml", +    "/SpringTest-context_basic_realConfig.xml"}) +@TestPropertySource(locations = { +    //"classpath:/application.properties", +    "file:/home/tlenz/Projekte/config/ms_connector/default_config.properties", +    }) +public class ErnpRestClientProductionTest { + +  //private static final String TEST_PREFIX = "XXX_"; +  private static final String TEST_PREFIX = ""; +   +  @Autowired IErnpClient client; +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdentifierServerError() { +    String personalIdentifierFirst = "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit"; +    personalIdentifierFirst = ""; +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("XXXvon Brandenburg") +        .givenName("XXXClaus - Maria") +        .dateOfBirth("1994-12-00") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +         +    // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchWithPersonIdentifier( +            eidasDataFirst.getPseudonym(), eidasDataFirst.getCitizenCountryCode())); +     +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId());    +         +  } +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdentifierSuccess() { +    final String personalIdentifierFirst = "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit"; +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("DOPISNÍ") +        .givenName("DANA") +        .dateOfBirth("1996-01-01") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +    +    // execute operation +    ErnpRegisterResult resp = client.searchWithPersonIdentifier( +        eidasDataFirst.getPseudonym(), eidasDataFirst.getCitizenCountryCode()); +         +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    checkErnpResult(resp.getPersonResult().get(0), eidasDataFirst, 1); +    assertEquals("wrong bpk", "vypyCkyczK7i+cgPWlJasuJphIA=",  +        resp.getPersonResult().get(0).getBpk()); +       +  } +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdentifierNoResult() { +    final String personalIdentifierFirst = RandomStringUtils.randomAlphanumeric(10); +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("DOPISNÍ") +        .givenName("DANA") +        .dateOfBirth("1996-01-01") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +    +    // execute operation +    ErnpRegisterResult resp = client.searchWithPersonIdentifier( +        eidasDataFirst.getPseudonym(), eidasDataFirst.getCitizenCountryCode()); +         +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 0, resp.getPersonResult().size()); +       +  } +   +   +  @Test +  @SneakyThrows +  public void searchWithMdsSuccess() { +    final String personalIdentifierFirst = "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit"; +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("DOPISNÍ") +        .givenName("DANA") +        .dateOfBirth("1996-01-01") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +    +    // execute operation +    ErnpRegisterResult resp = client.searchWithMds(eidasDataFirst.getGivenName(), eidasDataFirst.getFamilyName(),  +        eidasDataFirst.getDateOfBirth(), eidasDataFirst.getCitizenCountryCode()); +         +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    checkErnpResult(resp.getPersonResult().get(0), eidasDataFirst, 1); +    assertEquals("wrong bpk", "vypyCkyczK7i+cgPWlJasuJphIA=",  +        resp.getPersonResult().get(0).getBpk()); +                     +  } +   +  @Test +  @SneakyThrows +  public void searchWithMdsNoResult() { +    final String personalIdentifierFirst = RandomStringUtils.randomAlphanumeric(10); +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName(RandomStringUtils.randomAlphanumeric(10)) +        .givenName(RandomStringUtils.randomAlphanumeric(10)) +        .dateOfBirth("1996-10-15") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +    +    // execute operation +    ErnpRegisterResult resp = client.searchWithMds(eidasDataFirst.getGivenName(), eidasDataFirst.getFamilyName(),  +        eidasDataFirst.getDateOfBirth(), eidasDataFirst.getCitizenCountryCode()); +         +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 0, resp.getPersonResult().size()); +       +  } +   +  @Test +  @SneakyThrows +  public void addTwiceSameMdsAndMdsSearch() {     +    // *** add new random first person ***     +    final String addFirstPersonPersonalIdentifier = RandomStringUtils.randomAlphanumeric(10); +    final String cc = "XZ"; +    final SimpleEidasData addFirstPersonData = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .givenName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .dateOfBirth("1996-01-01") +        .personalIdentifier(cc + "/AT/" + addFirstPersonPersonalIdentifier) +        .pseudonym(addFirstPersonPersonalIdentifier) +        .build(); +     +    // add entry   +    ErnpRegisterResult addFirstPersonResponse = client.add(addFirstPersonData); +         +    // verify added entry +    assertNotNull("no ERnP response", addFirstPersonResponse); +    assertEquals("wrong resp size", 1, addFirstPersonResponse.getPersonResult().size()); +    checkErnpResult(addFirstPersonResponse.getPersonResult().get(0), addFirstPersonData, 1); +     +     +    // *** add new random second person with same MDS ***     +    final String addSecondPersonPersonalIdentifier = RandomStringUtils.randomAlphanumeric(10); +    final SimpleEidasData addSecondPersonData = addFirstPersonData.toBuilder() +        .personalIdentifier(cc + "/AT/" + addSecondPersonPersonalIdentifier) +        .pseudonym(addSecondPersonPersonalIdentifier) +        .build(); +     +    // add entry   +    ErnpRegisterResult addSecondPersonResponse = client.add(addSecondPersonData); +         +    // verify added entry +    assertNotNull("no ERnP response", addSecondPersonResponse); +    assertEquals("wrong resp size", 1, addSecondPersonResponse.getPersonResult().size()); +    checkErnpResult(addSecondPersonResponse.getPersonResult().get(0), addSecondPersonData, 1); + +     +     +    // search with MDS +    ErnpRegisterResult resp = client.searchWithMds(addFirstPersonData.getGivenName(), addFirstPersonData.getFamilyName(),  +        addFirstPersonData.getDateOfBirth(), cc); +         +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 2, resp.getPersonResult().size()); +         +  } +   +   +   +  @Test +  @SneakyThrows +  public void addSearchAndPersonalIdUpdate() {     +    // *** add new random entry *** +     +    final String addPersonPersonalIdentifier = RandomStringUtils.randomAlphanumeric(10); +    final String cc = "DE"; +    final SimpleEidasData addPersonData = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .givenName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .dateOfBirth("1996-01-01") +        .personalIdentifier(cc + "/AT/" + addPersonPersonalIdentifier) +        .pseudonym(addPersonPersonalIdentifier) +        .birthName(RandomStringUtils.randomAlphabetic(8)) +        .placeOfBirth(RandomStringUtils.randomAlphabetic(8)) +        .build(); +     +    // add entry   +    ErnpRegisterResult addPersonResponse = client.add(addPersonData); +         +    // verify added entry +    assertNotNull("no ERnP response", addPersonResponse); +    assertEquals("wrong resp size", 1, addPersonResponse.getPersonResult().size()); +    checkErnpResult(addPersonResponse.getPersonResult().get(0), addPersonData, 1); +     +     +    // *** search entry by countrySpecifics ***         +    final String ccPersonPersonalIdentifier = RandomStringUtils.randomAlphanumeric(10); +    SimpleEidasData ccSpecificData = addPersonData.toBuilder() +        .personalIdentifier(cc + "/AT/" + ccPersonPersonalIdentifier) +        .pseudonym(ccPersonPersonalIdentifier) +        .build();                     +    PersonSuchenRequest ccSearchReq =  +        new DeSpecificDetailSearchProcessor().generateSearchRequest(ccSpecificData); +         +    // search CC specific +    ErnpRegisterResult ccSearchResponse = client.searchCountrySpecific(ccSearchReq, cc); +     +    // verify cc specific result +    assertNotNull("no ERnP response", ccSearchResponse); +    assertEquals("wrong resp size", 1, ccSearchResponse.getPersonResult().size()); +    RegisterResult ccSearchPersResult = ccSearchResponse.getPersonResult().get(0); +    checkErnpResult(ccSearchResponse.getPersonResult().get(0), addPersonData, 1);     +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(),  +        ccSearchPersResult.getBpk()); +    assertFalse("no PersonalId change detected", ccSpecificData.equalsRegisterData(ccSearchPersResult)); +     +         +    // *** update entry because PersonalId has changed ***     +    // update ERnP entry +    ErnpRegisterResult updateResponse = client.update(ccSearchPersResult, ccSpecificData); +    assertNotNull("no ERnP response", updateResponse); +    assertEquals("wrong resp size", 1, updateResponse.getPersonResult().size()); +    checkErnpResult(updateResponse.getPersonResult().get(0), addPersonData, 2);     +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(), ccSearchPersResult.getBpk()); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), addPersonPersonalIdentifier); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), ccPersonPersonalIdentifier); +     +     +     +    //  *** search by first personalIdentifier +    ErnpRegisterResult persIdSearchFirstResp = client.searchWithPersonIdentifier( +        addPersonPersonalIdentifier, cc);        +    assertNotNull("no ERnP response", persIdSearchFirstResp); +    assertEquals("wrong resp size", 1, persIdSearchFirstResp.getPersonResult().size()); +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(), ccSearchPersResult.getBpk()); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), addPersonPersonalIdentifier); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), ccPersonPersonalIdentifier); +    checkErnpResult(updateResponse.getPersonResult().get(0), addPersonData, 2); +     +         +     +    // *** search by second personalIdentifier +    ErnpRegisterResult persIdSearchSecondResp = client.searchWithPersonIdentifier( +        ccPersonPersonalIdentifier, cc);        +    assertNotNull("no ERnP response", persIdSearchSecondResp); +    assertEquals("wrong resp size", 1, persIdSearchSecondResp.getPersonResult().size()); +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(), ccSearchPersResult.getBpk()); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), addPersonPersonalIdentifier); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), ccPersonPersonalIdentifier); +    checkErnpResult(updateResponse.getPersonResult().get(0), addPersonData, 2); +         +  } +     +  @Test +  @SneakyThrows +  public void addSearchAndMdsUpdate() {     +    // *** add new random entry *** +     +    final String addPersonPersonalIdentifier = RandomStringUtils.randomAlphanumeric(10); +    final String cc = "DE"; +    final SimpleEidasData addPersonData = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .givenName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .dateOfBirth("1985-05-05") +        .personalIdentifier(cc + "/AT/" + addPersonPersonalIdentifier) +        .pseudonym(addPersonPersonalIdentifier) +        .birthName(RandomStringUtils.randomAlphabetic(8)) +        .placeOfBirth(RandomStringUtils.randomAlphabetic(8)) +        .build(); +     +    // add entry   +    ErnpRegisterResult addPersonResponse = client.add(addPersonData); +         +    // verify added entry +    assertNotNull("no ERnP response", addPersonResponse); +    assertEquals("wrong resp size", 1, addPersonResponse.getPersonResult().size()); +    checkErnpResult(addPersonResponse.getPersonResult().get(0), addPersonData, 1); +     +     +    // *** search entry by personalId ***            +    SimpleEidasData mdsHasChanged = addPersonData.toBuilder() +        .givenName(RandomStringUtils.randomAlphanumeric(10)) +        .familyName(RandomStringUtils.randomAlphanumeric(10)) +        .build();                     +         +    // search by personalId +    ErnpRegisterResult personalIdResponse = client.searchWithPersonIdentifier(addPersonPersonalIdentifier, cc); +     +    // verify personalId result +    assertNotNull("no ERnP response", personalIdResponse); +    assertEquals("wrong resp size", 1, personalIdResponse.getPersonResult().size()); +    RegisterResult persIdSearchResult = personalIdResponse.getPersonResult().get(0); +    checkErnpResult(personalIdResponse.getPersonResult().get(0), addPersonData, 1);     +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(),  +        persIdSearchResult.getBpk());     +    assertFalse("no MDS change detected", mdsHasChanged.equalsRegisterData(persIdSearchResult)); +     +             +    // *** update entry because MDS has changed ***     +    // update ERnP entry +    ErnpRegisterResult updateResponse = client.update(persIdSearchResult, mdsHasChanged); +    assertNotNull("no ERnP response", updateResponse); +    assertEquals("wrong resp size", 1, updateResponse.getPersonResult().size()); +    checkErnpResult(updateResponse.getPersonResult().get(0), mdsHasChanged, 1);     +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(), persIdSearchResult.getBpk()); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), addPersonPersonalIdentifier); +         +     +    //  *** search by first personalIdentifier +    ErnpRegisterResult persIdSearchFirstResp = client.searchWithPersonIdentifier( +        addPersonPersonalIdentifier, cc);        +    assertNotNull("no ERnP response", persIdSearchFirstResp); +    assertEquals("wrong resp size", 1, persIdSearchFirstResp.getPersonResult().size()); +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(), persIdSearchResult.getBpk()); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), addPersonPersonalIdentifier); +    checkErnpResult(updateResponse.getPersonResult().get(0), mdsHasChanged, 1); +       +    //  *** search by first personalIdentifier +    ErnpRegisterResult mdsSearchResp = client.searchWithMds( +        mdsHasChanged.getGivenName(), mdsHasChanged.getFamilyName(), mdsHasChanged.getDateOfBirth(), cc); +    assertNotNull("no ERnP response", mdsSearchResp); +    assertEquals("wrong resp size", 1, mdsSearchResp.getPersonResult().size()); +    assertEquals("wrong bPK", addPersonResponse.getPersonResult().get(0).getBpk(), persIdSearchResult.getBpk()); +    checkPersonalIdentifier(updateResponse.getPersonResult().get(0), addPersonPersonalIdentifier); +    checkErnpResult(updateResponse.getPersonResult().get(0), mdsHasChanged, 1); +     +     +     +  } +   +   +  @Ignore +  @Test +  @SneakyThrows +  public void addErnpEntry() { +    final String personalIdentifierFirst = "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit"; +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("DOPISNÍ") +        .givenName("DANA") +        .dateOfBirth("1996-01-01") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +    +    // execute operation +    ErnpRegisterResult resp = client.add(eidasDataFirst); +            +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    checkErnpResult(resp.getPersonResult().get(0), eidasDataFirst, 1); +        +  } +   +  @Test +  @SneakyThrows +  public void addRandomErnpEntry() { +    final String addPersonPersonalIdentifier = RandomStringUtils.randomAlphanumeric(10); +    final String cc = "XZ"; +    final SimpleEidasData addPersonData = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .givenName(TEST_PREFIX + RandomStringUtils.randomAlphabetic(8)) +        .dateOfBirth("1985-05-05") +        .personalIdentifier(cc + "/AT/" + addPersonPersonalIdentifier) +        .pseudonym(addPersonPersonalIdentifier) +        .birthName(RandomStringUtils.randomAlphabetic(8)) +        .placeOfBirth(RandomStringUtils.randomAlphabetic(8)) +        .build(); +     +    // add entry   +    ErnpRegisterResult addPersonResponse = client.add(addPersonData); +         +    // verify added entry +    assertNotNull("no ERnP response", addPersonResponse); +    assertEquals("wrong resp size", 1, addPersonResponse.getPersonResult().size()); +    checkErnpResult(addPersonResponse.getPersonResult().get(0), addPersonData, 1); +        +  } +   +   +  private void checkErnpResult(RegisterResult registerResult, final SimpleEidasData eidasData, int numOfPseudonyms) { +    assertEquals("wrong familyname", eidasData.getFamilyName(), registerResult.getFamilyName());     +    assertEquals("wrong givenname", eidasData.getGivenName(), registerResult.getGivenName()); +    assertEquals("wrong birthday", eidasData.getDateOfBirth(), registerResult.getDateOfBirth()); +    assertEquals("wrong personalId size", numOfPseudonyms, registerResult.getPseudonym().size());         +    assertEquals("wrong placeOfBirth", eidasData.getPlaceOfBirth(), registerResult.getPlaceOfBirth()); +    assertEquals("wrong birthName", eidasData.getBirthName(), registerResult.getBirthName()); +    assertTrue("no bPK", StringUtils.isNotEmpty(registerResult.getBpk()));     +    checkPersonalIdentifier(registerResult, eidasData.getPseudonym()); +     +  } +   +  private void checkPersonalIdentifier(RegisterResult registerResult, String pseudonym) { +    assertTrue("wrong or no personalId", registerResult.getPseudonym().stream() +        .filter(el -> pseudonym.equals(el)) +        .findFirst() +        .isPresent()); +     +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientTest.java new file mode 100644 index 00000000..ab1a502c --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ErnpRestClientTest.java @@ -0,0 +1,1085 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.clients; + +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 java.net.HttpURLConnection; +import java.util.Arrays; +import java.util.Iterator; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummyConfigMap; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient; +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.exception.EidasSAuthenticationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.DeSpecificDetailSearchProcessor; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; +import lombok.SneakyThrows; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import okhttp3.mockwebserver.SocketPolicy; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { +    "/SpringTest-context_tasks_test.xml", +    "/SpringTest-context_basic_mapConfig.xml" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class ErnpRestClientTest { + +  @Autowired MsConnectorDummyConfigMap basicConfig; +  @Autowired IErnpClient client; +   +  private static ObjectMapper mapper = new ObjectMapper(); +  private static MockWebServer mockWebServer; +   +  /** +   * JUnit class initializer. +   * +   * @throws Exception In case of an OpenSAML3 initialization error +   */ +  @BeforeClass +  @SneakyThrows +  public static void classInitializer() { +    mockWebServer = new MockWebServer(); +    mockWebServer.start(1718); + +  } +   +  @AfterClass +  @SneakyThrows +  public static void resetTestEnviroment() { +    mockWebServer.shutdown(); + +  } +   +  /** +   * jUnit test initializer. +   * +   * @throws InterruptedException in case of an error +   */ +  @Before +  public void initialize() throws InterruptedException { +    mockWebServer.takeRequest(2, TimeUnit.MILLISECONDS); +    TransactionIdUtils.setTransactionId(UUID.randomUUID().toString()); +     +  } +   +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdentifierServerError() { +    final String personalIdentifierFirst = "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit"; +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("XXXvon Brandenburg") +        .givenName("XXXClaus - Maria") +        .dateOfBirth("1994-12-31") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(500) +        .setBody("Internal error")); +     +    // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchWithPersonIdentifier( +            eidasDataFirst.getPseudonym(), eidasDataFirst.getCitizenCountryCode())); +     +    mockWebServer.takeRequest(); +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId());    +         +  } +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdentifierSuccess() { +    final String personalIdentifierFirst = "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit"; +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("XXXvon Brandenburg") +        .givenName("XXXClaus - Maria") +        .dateOfBirth("1994-12-31") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); + +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/ernp_handbook_example.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); + +     +    // execute operation +    ErnpRegisterResult resp = client.searchWithPersonIdentifier( +        eidasDataFirst.getPseudonym(), eidasDataFirst.getCitizenCountryCode()); +     +    // validate request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +     +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); + +      +  } + +  @Test +  @SneakyThrows +  public void searchResidence() {     +     // execute operation +    ErnpRegisterResult resp = client.searchWithResidenceData(null, null, null, null, null, null);            +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 0, resp.getPersonResult().size()); +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithMdsNoResponse() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +             +    mockWebServer.enqueue(new MockResponse() +        .setSocketPolicy(SocketPolicy.NO_RESPONSE) +        .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)); +     +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchWithMds(eidasDataFirst.getGivenName(), eidasDataFirst.getFamilyName(), eidasDataFirst.getDateOfBirth(), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId()); +    mockWebServer.takeRequest();     +     +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithMdsErrorResponse() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(400) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/error_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchWithMds(eidasDataFirst.getGivenName(), eidasDataFirst.getFamilyName(), eidasDataFirst.getDateOfBirth(), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId());   +    mockWebServer.takeRequest(); +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithMdsNoResult() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/ernp_empty_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchWithMds(eidasDataFirst.getGivenName(), eidasDataFirst.getFamilyName(), eidasDataFirst.getDateOfBirth(), cc); +         +    // validate request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkSearchOptions(reqJson, "Searching with MDS only"); +    JsonNode person = getJsonObject(reqJson, "suchdaten"); +    checkJsonElement(person, "familienname", eidasDataFirst.getFamilyName()); +    checkJsonElement(person, "vorname", eidasDataFirst.getGivenName()); +    checkPersonDateOfBirth(person, eidasDataFirst.getDateOfBirth()); +         +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 0, resp.getPersonResult().size()); +         +  } +   +  @Test +  @SneakyThrows +  public void searchWithMdsSingleResult() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/3_search_with_mds_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchWithMds(eidasDataFirst.getGivenName(), eidasDataFirst.getFamilyName(), eidasDataFirst.getDateOfBirth(), cc); +                 +    // validate state +    mockWebServer.takeRequest(); +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", "DOPISNÍ", persInfo.getFamilyName()); +    assertEquals("wrong givenName", "DANA", persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", "1996-01-01", persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", "vypyCkyczK7i+cgPWlJasuJphIA=", persInfo.getBpk());     +    assertEquals("wrong pseudonym", "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit", persInfo.getPseudonym().get(0)); +    assertNull("placeOfBirth", persInfo.getPlaceOfBirth());    +    assertNull("birthName", persInfo.getBirthName());  +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithMdsMultiResult() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/4_search_with_mds_multi_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchWithMds(eidasDataFirst.getGivenName(), eidasDataFirst.getFamilyName(), eidasDataFirst.getDateOfBirth(), cc); +                 +    // validate state +    mockWebServer.takeRequest(); +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 2, resp.getPersonResult().size()); +     +  } +   +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdNoResponse() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +             +    mockWebServer.enqueue(new MockResponse() +        .setSocketPolicy(SocketPolicy.NO_RESPONSE) +        .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)); +         +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchWithPersonIdentifier(eidasDataFirst.getPseudonym(), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId()); +    mockWebServer.takeRequest();     +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdErrorResponse() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(400) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/error_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchWithPersonIdentifier(eidasDataFirst.getPseudonym(), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId()); +    mockWebServer.takeRequest(); +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdNoResult() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/ernp_empty_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchWithPersonIdentifier(eidasDataFirst.getPseudonym(), cc); +         +    // validate request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkSearchOptions(reqJson, "Searching PersonIdentifier"); +    JsonNode person = getJsonObject(reqJson, "suchdaten"); +    checkEidasDocument(person, "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", cc, eidasDataFirst.getPseudonym()); +     +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 0, resp.getPersonResult().size()); +         +  } +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdSingleResult() { +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/1_search_with_personalId_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchWithPersonIdentifier(eidasDataFirst.getPseudonym(), cc); +                 +    // validate state +    mockWebServer.takeRequest(); +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", "CtKKrtUe", persInfo.getFamilyName()); +    assertEquals("wrong givenName", "dUeYzUFg", persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", "1985-05-05", persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", "+OQnljn0Son1W2rkM73nP/VMsvc=", persInfo.getBpk());     +    assertEquals("wrong pseudonym", "Y8ADWaeh0h", persInfo.getPseudonym().get(0)); +    assertEquals("wrong placeOfBirth", "hrFevCfP", persInfo.getPlaceOfBirth());    +    assertEquals("wrong birthName", "sNUEAhEr", persInfo.getBirthName());    +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdSingleResultCountryNoMatch() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/1_search_with_personalId_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchWithPersonIdentifier(eidasDataFirst.getPseudonym(), cc); +                 +    // validate state +    mockWebServer.takeRequest(); +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", "CtKKrtUe", persInfo.getFamilyName()); +    assertEquals("wrong givenName", "dUeYzUFg", persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", "1985-05-05", persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", "+OQnljn0Son1W2rkM73nP/VMsvc=", persInfo.getBpk());     +    assertTrue("pseudonym", persInfo.getPseudonym().isEmpty()); +    assertNull("placeOfBirth", persInfo.getPlaceOfBirth());    +    assertNull("birthName", persInfo.getBirthName());    +     +  } +   +   +  @Test +  @SneakyThrows +  public void searchWithPersonalIdMultiResult() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/4_search_with_mds_multi_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchWithPersonIdentifier(eidasDataFirst.getPseudonym(), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.03", error.getErrorId()); +    mockWebServer.takeRequest(); +     +  } +   +   +  @Test +  @SneakyThrows +  public void searchWithCcspecificsNoResponse() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +             +    mockWebServer.enqueue(new MockResponse() +        .setSocketPolicy(SocketPolicy.NO_RESPONSE) +        .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)); +     +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchCountrySpecific(new DeSpecificDetailSearchProcessor().generateSearchRequest(eidasDataFirst), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId()); +    mockWebServer.takeRequest();     +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithCcspecificsErrorResponse() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(400) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/error_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchCountrySpecific(new DeSpecificDetailSearchProcessor().generateSearchRequest(eidasDataFirst), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId()); +    mockWebServer.takeRequest(); +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithCcspecificsNoResult() { +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc).toBuilder() +      .birthName(RandomStringUtils.randomAlphabetic(5)) +      .placeOfBirth(RandomStringUtils.randomAlphabetic(5)) +      .build(); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/ernp_empty_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchCountrySpecific( +        new DeSpecificDetailSearchProcessor().generateSearchRequest(eidasDataFirst), cc); +         +    // validate request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkSearchOptions(reqJson, "Searching DE specific"); +    JsonNode person = getJsonObject(reqJson, "suchdaten"); +    checkJsonElement(person, "familienname", eidasDataFirst.getFamilyName()); +    checkJsonElement(person, "vorname", eidasDataFirst.getGivenName()); +    checkPersonDateOfBirth(person, eidasDataFirst.getDateOfBirth()); +    checkEidasDocument(person, "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", cc, eidasDataFirst.getPlaceOfBirth()); +    checkEidasDocument(person, "http://eidas.europa.eu/attributes/naturalperson/BirthName", cc, eidasDataFirst.getBirthName()); +     +    // validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 0, resp.getPersonResult().size()); +         +  } +   +  @Test +  @SneakyThrows +  public void searchWithCcspecificsSingleResult() { +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/1_search_with_personalId_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchCountrySpecific( +        new DeSpecificDetailSearchProcessor().generateSearchRequest(eidasDataFirst), cc); +                 +    // validate state +    mockWebServer.takeRequest(); +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", "CtKKrtUe", persInfo.getFamilyName()); +    assertEquals("wrong givenName", "dUeYzUFg", persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", "1985-05-05", persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", "+OQnljn0Son1W2rkM73nP/VMsvc=", persInfo.getBpk());     +    assertEquals("wrong pseudonym", "Y8ADWaeh0h", persInfo.getPseudonym().get(0)); +    assertEquals("wrong placeOfBirth", "hrFevCfP", persInfo.getPlaceOfBirth());    +    assertEquals("wrong birthName", "sNUEAhEr", persInfo.getBirthName());    +     +  } +   +  @Test +  @SneakyThrows +  public void searchWithCcspecificsSingleResultCountryNoMatch() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/1_search_with_personalId_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    ErnpRegisterResult resp = client.searchCountrySpecific( +        new DeSpecificDetailSearchProcessor().generateSearchRequest(eidasDataFirst), cc); +                 +    // validate state +    mockWebServer.takeRequest(); +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", "CtKKrtUe", persInfo.getFamilyName()); +    assertEquals("wrong givenName", "dUeYzUFg", persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", "1985-05-05", persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", "+OQnljn0Son1W2rkM73nP/VMsvc=", persInfo.getBpk());     +    assertTrue("pseudonym", persInfo.getPseudonym().isEmpty()); +    assertNull("placeOfBirth", persInfo.getPlaceOfBirth());    +    assertNull("birthName", persInfo.getBirthName());    +     +  } +   +   +  @Test +  @SneakyThrows +  public void searchWithCcspecificsMultiResult() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +     +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/4_search_with_mds_multi_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.searchCountrySpecific(new DeSpecificDetailSearchProcessor().generateSearchRequest(eidasDataFirst), cc));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.03", error.getErrorId()); +    mockWebServer.takeRequest(); +     +  } +   +   +  @Test +  @SneakyThrows +  public void addPersonNoResponse() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +             +    mockWebServer.enqueue(new MockResponse() +        .setSocketPolicy(SocketPolicy.NO_RESPONSE) +        .setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)); +     +     // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.add(eidasDataFirst));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.11", error.getErrorId()); +    mockWebServer.takeRequest();     +     +  } +   +  @Test +  @SneakyThrows +  public void addPersonSimpleSuccess() { +    final String cc = "CZ"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc); +             +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/2_add_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +     // execute operation +    // execute operation +    ErnpRegisterResult resp = client.add(eidasDataFirst); +         +    // validate request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkJsonElement(reqJson, "begruendung", "Add new person"); +    JsonNode person = getJsonObject(reqJson, "personendaten"); +    checkJsonElement(person, "familienname", eidasDataFirst.getFamilyName()); +    checkJsonElement(person, "vorname", eidasDataFirst.getGivenName()); +    checkPersonDateOfBirth(person, eidasDataFirst.getDateOfBirth()); +    checkEidasDocument(reqJson, "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", cc, eidasDataFirst.getPseudonym()); +    checkEidasDocument(reqJson, "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", cc); +    checkEidasDocument(reqJson, "http://eidas.europa.eu/attributes/naturalperson/BirthName", cc); +     +     +    // validate state   +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", "mRjMKAQc", persInfo.getFamilyName()); +    assertEquals("wrong givenName", "vdqZZIaA", persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", "1996-01-01", persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", "TBGoMlirU881e2jMGETa9WLx1+A=", persInfo.getBpk());     +      +  } +   +  @Test +  @SneakyThrows +  public void addPersonSimpleComplexe() { +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc).toBuilder() +        .birthName(RandomStringUtils.randomAlphabetic(5)) +        .placeOfBirth(RandomStringUtils.randomAlphabetic(5)) +        .build(); +             +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/2_add_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +     // execute operation +    // execute operation +    ErnpRegisterResult resp = client.add(eidasDataFirst); +         +    // validate request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkJsonElement(reqJson, "begruendung", "Add new person"); +    JsonNode person = getJsonObject(reqJson, "personendaten"); +    checkJsonElement(person, "familienname", eidasDataFirst.getFamilyName()); +    checkJsonElement(person, "vorname", eidasDataFirst.getGivenName()); +    checkPersonDateOfBirth(person, eidasDataFirst.getDateOfBirth()); +    checkEidasDocument(reqJson, "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", cc, eidasDataFirst.getPseudonym()); +    checkEidasDocument(reqJson, "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", cc, eidasDataFirst.getPlaceOfBirth()); +    checkEidasDocument(reqJson, "http://eidas.europa.eu/attributes/naturalperson/BirthName", cc, eidasDataFirst.getBirthName()); +     +    // validate state   +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", "mRjMKAQc", persInfo.getFamilyName()); +    assertEquals("wrong givenName", "vdqZZIaA", persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", "1996-01-01", persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", "TBGoMlirU881e2jMGETa9WLx1+A=", persInfo.getBpk()); +    assertEquals("wrong pseudonym", "88hvWzUaIX", persInfo.getPseudonym().get(0)); +    assertEquals("wrong placeOfBirth", "VRNCAylF", persInfo.getPlaceOfBirth());    +    assertEquals("wrong birthName", "miEklFHC", persInfo.getBirthName());   +     +  } +   +  @Test +  @SneakyThrows +  public void updateNoLatestVersion() { +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = generateRandomEidasData(cc).toBuilder() +        .birthName(RandomStringUtils.randomAlphabetic(5)) +        .placeOfBirth(RandomStringUtils.randomAlphabetic(5)) +        .build(); +             +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/ernp_empty_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +     RegisterResult ernpResult = RegisterResult.builder() +         .familyName(eidasDataFirst.getFamilyName()) +         .givenName(eidasDataFirst.getGivenName()) +         .dateOfBirth(eidasDataFirst.getDateOfBirth()) +         .bpk("") +         .pseudonym(Arrays.asList(eidasDataFirst.getPseudonym())) +         .build();      +      +    // execute operation +    EidasSAuthenticationException error = assertThrows("wrong Exception", EidasSAuthenticationException.class, +        () -> client.update(ernpResult, eidasDataFirst));         +    assertEquals("wrong errorCode", "module.eidasauth.matching.03", error.getErrorId()); +    mockWebServer.takeRequest();   +     +     +  } +   +   +  @Test +  @SneakyThrows +  public void updateNoUpdateRequired() { +    final String cc = "DE"; +    final String personalIdentifierFirst = "Y8ADWaeh0h"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("CtKKrtUe") +        .givenName("dUeYzUFg") +        .dateOfBirth("1985-05-05") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +             +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/1_kitt_search_latest_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +     RegisterResult ernpResult = RegisterResult.builder() +         .familyName(eidasDataFirst.getFamilyName()) +         .givenName(eidasDataFirst.getGivenName()) +         .dateOfBirth(eidasDataFirst.getDateOfBirth()) +         .bpk("+OQnljn0Son1W2rkM73nP/VMsvc=") +         .pseudonym(Arrays.asList(eidasDataFirst.getPseudonym())) +         .birthName("sNUEAhEr") +         .placeOfBirth("hrFevCfP") +         .build();      +      +    // execute operation +    ErnpRegisterResult resp = client.update(ernpResult, eidasDataFirst); +     +    // validate request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkSearchOptions(reqJson, "KITT get-latest-version"); +    JsonNode person = getJsonObject(reqJson, "suchdaten"); +    checkJsonElement(person, "familienname", ernpResult.getFamilyName()); +    checkJsonElement(person, "vorname", ernpResult.getGivenName()); +    checkJsonElement(person, "bpkZp", ernpResult.getBpk()); +    checkPersonDateOfBirth(person, ernpResult.getDateOfBirth()); +     +    //validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", ernpResult.getFamilyName(), persInfo.getFamilyName()); +    assertEquals("wrong givenName", ernpResult.getGivenName(), persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", ernpResult.getDateOfBirth(), persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", ernpResult.getBpk(), persInfo.getBpk()); +    assertEquals("wrong pseudonym", ernpResult.getPseudonym().get(0), persInfo.getPseudonym().get(0)); +    assertEquals("wrong placeOfBirth", "hrFevCfP", persInfo.getPlaceOfBirth());    +    assertEquals("wrong birthName", "sNUEAhEr", persInfo.getBirthName()); +         +  } +   +  @Test +  @SneakyThrows +  public void updateUpdateRequiredMds() { +    final String cc = "DE"; +    final String personalIdentifierFirst = "Y8ADWaeh0h"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("mVzTMpig6r") +        .givenName("Jb2vj1Xpql") +        .dateOfBirth("1985-05-05") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .placeOfBirth("hrFevCfP") +        .birthName("sNUEAhEr") +        .build(); +             +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/1_kitt_search_latest_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/1_kitt_update_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +     RegisterResult ernpResult = RegisterResult.builder() +         .familyName("CtKKrtUe") +         .givenName("dUeYzUFg") +         .dateOfBirth("1985-05-05") +         .bpk("+OQnljn0Son1W2rkM73nP/VMsvc=") +         .pseudonym(Arrays.asList("Y8ADWaeh0h")) +         .birthName("sNUEAhEr") +         .placeOfBirth("hrFevCfP") +         .build();      +      +    // execute operation +    ErnpRegisterResult resp = client.update(ernpResult, eidasDataFirst); +     +    // validate request +    //  check get-latest-version request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkSearchOptions(reqJson, "KITT get-latest-version"); +    JsonNode person = getJsonObject(reqJson, "suchdaten"); +    checkJsonElement(person, "familienname", ernpResult.getFamilyName()); +    checkJsonElement(person, "vorname", ernpResult.getGivenName()); +    checkJsonElement(person, "bpkZp", ernpResult.getBpk()); +    checkPersonDateOfBirth(person, ernpResult.getDateOfBirth()); +     +    //  check update request +    final RecordedRequest requestKitt = mockWebServer.takeRequest(); +    String reqBodyKitt = requestKitt.getBody().readUtf8(); +    assertFalse("no request body", reqBodyKitt.isEmpty()); +    JsonNode reqJsonKitt = mapper.readTree(reqBodyKitt); +    checkJsonElement(reqJsonKitt, "begruendung", "KITT update dataset"); +    checkJsonElement(reqJsonKitt, "entityId", "1933000000000475"); +    checkJsonElement(reqJsonKitt, "version", "2022-03-03T10:07:28.885Z");             +    JsonNode personChange = getJsonObject(reqJsonKitt, "aendern"); +    JsonNode personKitt = getJsonObject(personChange, "personendaten"); +    checkJsonElement(personKitt, "familienname", eidasDataFirst.getFamilyName()); +    checkJsonElement(personKitt, "vorname", eidasDataFirst.getGivenName()); +    checkPersonDateOfBirth(personKitt, eidasDataFirst.getDateOfBirth()); +     +    assertFalse("find 'aendern' element", reqJsonKitt.has("anlegen")); +    assertFalse("find 'aendern' element", personChange.has("eidas")); +     +     +    //validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", eidasDataFirst.getFamilyName(), persInfo.getFamilyName()); +    assertEquals("wrong givenName", eidasDataFirst.getGivenName(), persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", ernpResult.getDateOfBirth(), persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", ernpResult.getBpk(), persInfo.getBpk()); +    assertEquals("wrong pseudonym", ernpResult.getPseudonym().get(0), persInfo.getPseudonym().get(0)); +    assertEquals("wrong placeOfBirth", "hrFevCfP", persInfo.getPlaceOfBirth());    +    assertEquals("wrong birthName", "sNUEAhEr", persInfo.getBirthName()); +         +  } +   +  @Test +  @SneakyThrows +  public void updateUpdateRequiredEidasDocs() { +    final String cc = "DE"; +    final String personalIdentifierFirst = "nj1m79jm9z"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("mRjMKAQc") +        .givenName("vdqZZIaA") +        .dateOfBirth("1996-01-01") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .birthName(RandomStringUtils.randomAlphabetic(10)) +        .build(); +             +    // set ERnP response +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/2_kitt_search_latest_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/2_kitt_update_resp.json"),  +            "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +     RegisterResult ernpResult = RegisterResult.builder() +         .familyName("mRjMKAQc") +         .givenName("vdqZZIaA") +         .dateOfBirth("1996-01-01") +         .bpk("TBGoMlirU881e2jMGETa9WLx1+A=") +         .pseudonym(Arrays.asList("88hvWzUaIX")) +         .birthName("VRNCAylF") +         .placeOfBirth("miEklFHC") +         .build();      +      +    // execute operation +    ErnpRegisterResult resp = client.update(ernpResult, eidasDataFirst); +     +    // validate request +    //  check get-latest-version request +    final RecordedRequest request = mockWebServer.takeRequest(); +    String reqBody = request.getBody().readUtf8(); +    assertFalse("no request body", reqBody.isEmpty()); +    JsonNode reqJson = mapper.readTree(reqBody); +    checkSearchOptions(reqJson, "KITT get-latest-version"); +    JsonNode person = getJsonObject(reqJson, "suchdaten"); +    checkJsonElement(person, "familienname", ernpResult.getFamilyName()); +    checkJsonElement(person, "vorname", ernpResult.getGivenName()); +    checkJsonElement(person, "bpkZp", ernpResult.getBpk()); +    checkPersonDateOfBirth(person, ernpResult.getDateOfBirth()); +     +    //  check update request +    final RecordedRequest requestKitt = mockWebServer.takeRequest(); +    String reqBodyKitt = requestKitt.getBody().readUtf8(); +    assertFalse("no request body", reqBodyKitt.isEmpty()); +    JsonNode reqJsonKitt = mapper.readTree(reqBodyKitt); +    checkJsonElement(reqJsonKitt, "begruendung", "KITT update dataset"); +    checkJsonElement(reqJsonKitt, "entityId", "1933000000000498"); +    checkJsonElement(reqJsonKitt, "version", "2022-03-03T10:14:59.712Z");             +    JsonNode personChange = getJsonObject(reqJsonKitt, "anlegen"); +    checkEidasDocument(personChange, "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", cc, eidasDataFirst.getPseudonym());     +    assertFalse("find 'aendern' element", reqJsonKitt.has("aendern")); +             +    //validate state +    assertNotNull("no ERnP response", resp); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("wrong familyname", eidasDataFirst.getFamilyName(), persInfo.getFamilyName()); +    assertEquals("wrong givenName", eidasDataFirst.getGivenName(), persInfo.getGivenName()); +    assertEquals("wrong dateOfBirth", ernpResult.getDateOfBirth(), persInfo.getDateOfBirth());     +    assertEquals("wrong bpk", ernpResult.getBpk(), persInfo.getBpk()); +    assertEquals("wrong pseudonym", ernpResult.getPseudonym().get(0), persInfo.getPseudonym().get(0)); +    assertEquals("wrong pseudonym", eidasDataFirst.getPseudonym(), persInfo.getPseudonym().get(1)); +    assertEquals("wrong placeOfBirth", "VRNCAylF", persInfo.getPlaceOfBirth());    +    assertEquals("wrong birthName", "miEklFHC", persInfo.getBirthName()); +         +  } +   +   +  private SimpleEidasData generateRandomEidasData(String cc) { +    final String personalIdentifierFirst = RandomStringUtils.randomAlphanumeric(10); +    return SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName(RandomStringUtils.randomAlphanumeric(10)) +        .givenName(RandomStringUtils.randomAlphanumeric(10)) +        .dateOfBirth("1996-10-15") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); +     +  } +  +  private void checkEidasDocument(JsonNode person, String art, String cc, String expected) { +    assertTrue("no element: eidas", person.has("eidas")); +    assertTrue("wrong type element: eidas", person.get("eidas").isArray()); +     +    boolean found = false; +    Iterator<JsonNode> docs = person.get("eidas").elements(); +    while (docs.hasNext() && !found) { +      JsonNode el = docs.next(); +      assertTrue("art", el.has("art"));   +      assertTrue("wert", el.has("wert")); +      assertTrue("cc", el.has("staatscode2"));             +      found = art.equals(el.get("art").asText()) && cc.equals(el.get("staatscode2").asText()) +          && expected.equals(el.get("wert").asText()); +       +    }     +    assertTrue("Missing eidas document", found); +     +  } +   +  private void checkEidasDocument(JsonNode person, String art, String cc) { +    assertTrue("no element: eidas", person.has("eidas")); +    assertTrue("wrong type element: eidas", person.get("eidas").isArray()); +     +    boolean found = false; +    Iterator<JsonNode> docs = person.get("eidas").elements(); +    while (docs.hasNext() && !found) { +      JsonNode el = docs.next(); +      assertTrue("art", el.has("art"));   +      assertTrue("wert", el.has("wert")); +      assertTrue("cc", el.has("staatscode2"));             +      found = art.equals(el.get("art").asText()) && cc.equals(el.get("staatscode2").asText()); +       +    }     +    assertFalse("Missing eidas document", found); +     +  } +   +  private void checkPersonDateOfBirth(JsonNode person, String dateOfBirth) { +    JsonNode birthDay = getJsonObject(person, "geburtsdatum");     +    String[] el = dateOfBirth.split("-"); +    checkJsonElement(birthDay, "jahr", Integer.parseInt(el[0]));     +    checkJsonElement(birthDay, "monat", Integer.parseInt(el[1])); +    checkJsonElement(birthDay, "tag", Integer.parseInt(el[2])); +     +  } + +  private void checkSearchOptions(JsonNode json, String reason) { +    checkJsonElement(json, "begruendung", reason); +    JsonNode options = getJsonObject(json, "suchoptionen"); +    checkJsonElement(options, "historisch", "AktuellUndHistorisch"); +    checkJsonElement(options, "sucheMitNamensteilen", false); +    checkJsonElement(options, "suchwizard", false); +    checkJsonElement(options, "zmr", false); +     +  } +   +  private JsonNode getJsonObject(JsonNode json, String key) { +    assertTrue("no element: " + key, json.has(key)); +    assertTrue("wrong type element: " + key, json.get(key).isObject()); +    return json.get(key); +     +  } +     +  private void checkJsonElement(JsonNode json, String key, int expected) {     +    assertTrue("no element: " + key, json.has(key)); +    assertTrue("wong element-type: " + key, json.get(key).isInt()); +    assertEquals("wong element-value: " + key, expected, json.get(key).asInt()); +     +  } +   +  private void checkJsonElement(JsonNode json, String key, String expected) {     +    assertTrue("no element: " + key, json.has(key)); +    assertTrue("wong element-type: " + key, json.get(key).isTextual()); +    assertEquals("wong element-value: " + key, expected, json.get(key).asText()); +     +  } +   +  private void checkJsonElement(JsonNode json, String key, boolean expected) {     +    assertTrue("no element: " + key, json.has(key)); +    assertTrue("wong element-type: " + key, json.get(key).isBoolean()); +    assertEquals("wong element-value: " + key, expected, json.get(key).asBoolean()); +     +  } +   +   +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientProductionTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientProductionTest.java index a5b83b13..fb52a729 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientProductionTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientProductionTest.java @@ -23,16 +23,8 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.clients; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.szr.SzrClient; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException; -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.idp.auth.data.IIdentityLink; -import at.gv.egiz.eaaf.core.exceptions.EaafParserException; -import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser; +import java.util.List; +  import org.apache.commons.lang3.RandomStringUtils;  import org.apache.commons.lang3.StringUtils;  import org.bouncycastle.util.encoders.Base64; @@ -47,10 +39,14 @@ import org.springframework.test.annotation.IfProfileValue;  import org.springframework.test.context.ContextConfiguration;  import org.springframework.test.context.TestPropertySource;  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.w3c.dom.Element; -import szrservices.IdentityLinkType; -import java.util.List; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.szr.SzrClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration;  @IfProfileValue(name = "spring.profiles.active", value = "devEnvironment") @@ -78,13 +74,6 @@ public class SzrClientProductionTest {    }    @Test -  public void getVsz() throws EidasSAuthenticationException { -    String vsz = szrClient.getEncryptedStammzahl(getEidData()); -    Assert.assertNotNull("vsz", vsz); - -  } - -  @Test    public void getEidasBind() throws EidasSAuthenticationException {      String vsz = RandomStringUtils.randomAlphanumeric(10);      String bindingPubKey = Base64.toBase64String(RandomStringUtils.random(20).getBytes()); @@ -96,52 +85,6 @@ public class SzrClientProductionTest {    } - -  @Test -  public void getIdentityLinkRawMode() throws EaafParserException, EidasSAuthenticationException { -    log.debug("Starting connecting SZR Gateway"); -    final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(getEidData()); - -    final Element idlFromSzr = (Element) result.getAssertion(); -    final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlFromSzr).parseIdentityLink(); - -    if (identityLink == null) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO IDL object" }); -    } - -    System.out.println(identityLink.getSerializedSamlAssertion()); - -    if (StringUtils.isEmpty(identityLink.getFamilyName())) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO FamilyName from IDL" }); -    } - -    if (StringUtils.isEmpty(identityLink.getGivenName())) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO GivenName from IDL" }); -    } - -    if (StringUtils.isEmpty(identityLink.getDateOfBirth())) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO DateOfBirthName from IDL" }); -    } - -    if (StringUtils.isEmpty(identityLink.getIdentificationType())) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO baseIdType from IDL" }); -    } - -    if (StringUtils.isEmpty(identityLink.getIdentificationValue())) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO baseId from IDL" }); -    } - -    if (StringUtils.isEmpty(identityLink.getSerializedSamlAssertion())) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO serialized IDL" }); -    } - -    if (identityLink.getSamlAssertion() == null) { -      throw new SzrCommunicationException("ernb.00", new Object[] { "NO raw IDL" }); -    } - -  } - -    @Ignore    @Test    public void getBpkTest() throws EidasSAuthenticationException { diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientTest.java index ee1ecf9f..c47c4fb0 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/SzrClientTest.java @@ -34,7 +34,6 @@ import javax.xml.bind.JAXBContext;  import javax.xml.bind.JAXBException;  import javax.xml.bind.Unmarshaller;  import javax.xml.parsers.ParserConfigurationException; -import javax.xml.ws.soap.SOAPFaultException;  import org.apache.commons.io.IOUtils;  import org.apache.commons.lang3.RandomStringUtils; @@ -63,15 +62,9 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException;  import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; -import at.gv.egiz.eaaf.core.exceptions.EaafParserException; -import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;  import at.gv.egiz.eaaf.core.impl.utils.DomUtils;  import lombok.extern.slf4j.Slf4j; -import szrservices.GetBPKFromStammzahlEncryptedResponse; -import szrservices.GetBPKFromStammzahlEncryptedResponseType;  import szrservices.GetIdentityLinkEidasResponse; -import szrservices.IdentityLinkType;  import szrservices.PersonInfoType;  import szrservices.SZR;  import szrservices.SZRException_Exception; @@ -110,33 +103,6 @@ public class SzrClientTest {    } -   -   - -  @Test -  public void getStammzahlenEcryptedTest() throws SZRException_Exception, SzrCommunicationException { -    final GetBPKFromStammzahlEncryptedResponse szrResponse = new GetBPKFromStammzahlEncryptedResponse(); -    final GetBPKFromStammzahlEncryptedResponseType result1 = new GetBPKFromStammzahlEncryptedResponseType(); -    szrResponse.getOut().add(result1); - -    result1.setKey(RandomStringUtils.randomAlphanumeric(20)); - -    //    when(szrMock.getBPKFromStammzahlEncrypted(anyList())) -    //        .thenReturn(Arrays.asList(result1)); -    when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(result1.getKey()); - -    String stammzahlEncrypted = szrClient.getEncryptedStammzahl(getEidData()); - -    Assert.assertEquals("bcBind not match", result1.getKey(), stammzahlEncrypted); - -    when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(null); -    try { -      szrClient.getEncryptedStammzahl(getEidData()); -    } catch (SzrCommunicationException e) { -      Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01")); -    } -  } -    @Test    public void getEidasBindRealSzrResponse() throws SZRException_Exception, SzrCommunicationException, IOException {      final SignContentResponse szrResponse = new SignContentResponse(); @@ -254,63 +220,6 @@ public class SzrClientTest {    } -  @Test -  public void getIdentityLinkRawModeValidResponse() -      throws SZRException_Exception, EaafParserException, JAXBException { -    setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml"); - -    try { -      log.debug("Starting connecting SZR Gateway"); -      final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(getEidData()); - -      Assert.assertNotNull(result); -      Assert.assertNotNull(result.getAssertion()); - -      final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser((Element) result.getAssertion()) -          .parseIdentityLink(); -      Assert.assertNotNull(identityLink); - -      System.out.println(identityLink.getSerializedSamlAssertion()); - -      checkElement("Mustermann", identityLink.getFamilyName()); -      checkElement("Hans", identityLink.getGivenName()); -      checkElement("1989-05-05", identityLink.getDateOfBirth()); -      checkElement("urn:publicid:gv.at:baseid", identityLink.getIdentificationType()); -      checkElement("k+zDM1BVpN1WJO4x7ZQ3ng==", identityLink.getIdentificationValue()); -      Assert.assertNotNull(identityLink.getSerializedSamlAssertion()); -      Assert.assertNotNull(identityLink.getSamlAssertion()); - -    } catch (final SzrCommunicationException e) { -      Assert.fail(); - -    } - -  } - -  @Test -  public void getIdentityLinkRawModeErrorTravelerDocExists() -      throws SZRException_Exception, IOException, ParserConfigurationException, SAXException { -    setSzrExceptionIdentityLink("/data/szr/szr_resp_error_travelerdocexists.xml"); - -    try { -      log.debug("Starting connecting SZR Gateway"); -      szrClient.getIdentityLinkInRawMode(getEidData()); -      Assert.fail(); - -    } catch (final SzrCommunicationException e) { -      checkElement("ernb.02", e.getErrorId()); -      Assert.assertNotNull(e.getCause()); -      org.springframework.util.Assert.isInstanceOf(SOAPFaultException.class, e.getCause()); -      Assert.assertNotNull(((SOAPFaultException) e.getCause()).getFault()); -      checkElement("p344:F455", ((SOAPFaultException) e.getCause()).getFault().getFaultCode()); -      checkElement( -          "The travel document you sent to insert a person already exists for another person. " + "Either check the document or have the person altered accordingly", -          ((SOAPFaultException) e.getCause()).getFault().getFaultString()); - -    } - -  } -    @Ignore    @Test    public void getBpkTest() throws EidasSAuthenticationException { diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ZmrClientTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ZmrClientTest.java index beedfda0..2ff9f0cb 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ZmrClientTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/clients/ZmrClientTest.java @@ -41,6 +41,7 @@ import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummyCo  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient.ZmrRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput;  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.exception.EidasSAuthenticationException; @@ -605,6 +606,168 @@ public class ZmrClientTest {    @Test    @SneakyThrows +  public void searchResidenceEmpty() { +    BigInteger processId = new BigInteger(RandomStringUtils.randomNumeric(6)); + +    final String cc = "DE"; +    String familyName = RandomStringUtils.randomAlphabetic(10); +    String givenName = RandomStringUtils.randomAlphabetic(10); +    String dateOfBirth = RandomStringUtils.randomAlphabetic(10);         +    AdresssucheOutput addressInfo = AdresssucheOutput.builder() +        .municipality(RandomStringUtils.randomAlphabetic(10)) +        .number(RandomStringUtils.randomAlphabetic(10)) +        .postleitzahl(RandomStringUtils.randomAlphabetic(10)) +        .street(RandomStringUtils.randomAlphabetic(10)) +        .village(RandomStringUtils.randomAlphabetic(10)) +        .build(); +     +     +    final ArgumentCaptor<RequestType> zmrReq = ArgumentCaptor.forClass(RequestType.class); + +    // inject response +    when(zmrMock.service(zmrReq.capture(), any())).thenReturn( +        loadResponseFromFile("/data/zmr/empty_zmr_result.xml")); +                 +    // execute operation +    ZmrRegisterResult resp = client.searchWithResidenceData(processId,  +        givenName, familyName, dateOfBirth, cc, addressInfo); +     +    // validate state +    assertNotNull("no ZMR response", resp); +    assertEquals("wrong processId", "367100000000079", resp.getProcessId().toString()); +    assertEquals("wrong resp size", 0, resp.getPersonResult().size()); +     +    // validate request +    assertEquals("wrong number of req.", 1, zmrReq.getAllValues().size()); +    assertNotNull("Personensuche req.", zmrReq.getValue().getPersonSuchenRequest()); +    checkBasicRequestParameters(zmrReq.getValue(), PROCESS_TASK_SEARCH, processId, "jUnit123456"); +    PersonSuchenRequest pSuche = zmrReq.getValue().getPersonSuchenRequest(); +    checkSearchParameters(pSuche.getPersonensucheInfo()); +    +    assertNotNull("mds", pSuche.getNatuerlichePerson()); +    assertEquals("req. givenName", givenName, pSuche.getNatuerlichePerson().getPersonenName().getVorname()); +    assertEquals("req. familyName", familyName, pSuche.getNatuerlichePerson().getPersonenName().getFamilienname()); +    assertEquals("req. dateOfBirth", dateOfBirth, pSuche.getNatuerlichePerson().getGeburtsdatum()); +     +    assertEquals("req. Municipality", addressInfo.getMunicipality(), pSuche.getPostAdresse().getGemeinde());     +    assertEquals("req. Postleitzahl", addressInfo.getPostleitzahl(), pSuche.getPostAdresse().getPostleitzahl()); +    assertEquals("req. Village", addressInfo.getVillage(), pSuche.getPostAdresse().getOrtschaft()); +    assertEquals("req. Street", addressInfo.getStreet(), pSuche.getPostAdresse().getZustelladresse().getStrassenname()); +    assertEquals("req. Number", addressInfo.getNumber(), pSuche.getPostAdresse().getZustelladresse().getOrientierungsnummer()); +     +  } +   +  @Test +  @SneakyThrows +  public void searchResidenceMoreThanOneResult() { +    BigInteger processId = new BigInteger(RandomStringUtils.randomNumeric(6)); + +    final String cc = "DE"; +    String familyName = RandomStringUtils.randomAlphabetic(10); +    String givenName = RandomStringUtils.randomAlphabetic(10); +    String dateOfBirth = RandomStringUtils.randomAlphabetic(10); +    AdresssucheOutput addressInfo = AdresssucheOutput.builder() +        .municipality(RandomStringUtils.randomAlphabetic(10)) +        .postleitzahl(RandomStringUtils.randomAlphabetic(10)) +        .street(RandomStringUtils.randomAlphabetic(10))         +        .build(); +     +    final ArgumentCaptor<RequestType> zmrReq = ArgumentCaptor.forClass(RequestType.class); + +    // inject response +    when(zmrMock.service(zmrReq.capture(), any())).thenReturn( +        loadResponseFromFile("/data/zmr/search_with_personalId_only_resp_moreThanOne.xml")); +     +    // execute operation +    ZmrRegisterResult resp = client.searchWithResidenceData(processId,  +        givenName, familyName, dateOfBirth, cc, addressInfo); +     +    // validate state +    assertNotNull("no ZMR response", resp); +    assertEquals("wrong processId", "367100000000079", resp.getProcessId().toString()); +    assertEquals("wrong resp size", 2, resp.getPersonResult().size()); +     +    // validate request +    assertEquals("wrong number of req.", 1, zmrReq.getAllValues().size()); +    assertNotNull("Personensuche req.", zmrReq.getValue().getPersonSuchenRequest()); +    checkBasicRequestParameters(zmrReq.getValue(), PROCESS_TASK_SEARCH, processId, "jUnit123456"); +    PersonSuchenRequest pSuche = zmrReq.getValue().getPersonSuchenRequest();    +    assertEquals("req. Municipality", addressInfo.getMunicipality(), pSuche.getPostAdresse().getGemeinde());     +    assertEquals("req. Postleitzahl", addressInfo.getPostleitzahl(), pSuche.getPostAdresse().getPostleitzahl()); +    assertNull("req. Village", pSuche.getPostAdresse().getOrtschaft()); +    assertEquals("req. Street", addressInfo.getStreet(), pSuche.getPostAdresse().getZustelladresse().getStrassenname()); +    assertNull("req. Number", pSuche.getPostAdresse().getZustelladresse().getOrientierungsnummer()); +     +  } +   +  @Test +  @SneakyThrows +  public void searchResidenceSuccess() { +    final String personalIdentifierFirst = "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit"; +    final String cc = "DE"; +    final SimpleEidasData eidasDataFirst = SimpleEidasData.builder() +        .citizenCountryCode(cc) +        .familyName("XXXvon Brandenburg") +        .givenName("XXXClaus - Maria") +        .dateOfBirth("1994-12-31") +        .personalIdentifier(cc + "/AT/" + personalIdentifierFirst) +        .pseudonym(personalIdentifierFirst) +        .build(); + +    BigInteger processId = new BigInteger(RandomStringUtils.randomNumeric(6)); + +    String familyName = RandomStringUtils.randomAlphabetic(10); +    String givenName = RandomStringUtils.randomAlphabetic(10); +    String dateOfBirth = RandomStringUtils.randomAlphabetic(10); +    AdresssucheOutput addressInfo = AdresssucheOutput.builder() +        .municipality(RandomStringUtils.randomAlphabetic(10)) +        .postleitzahl(RandomStringUtils.randomAlphabetic(10))         +        .build(); +     +    final ArgumentCaptor<RequestType> zmrReq = ArgumentCaptor.forClass(RequestType.class); + +    // inject response +    when(zmrMock.service(zmrReq.capture(), any())).thenReturn( +        loadResponseFromFile("/data/zmr/search_with_personalId_only_resp.xml")); +     +    // execute operation +    ZmrRegisterResult resp = client.searchWithResidenceData(processId,  +        givenName, familyName, dateOfBirth, cc, addressInfo); +     +    // validate state +    assertNotNull("no ZMR response", resp); +    assertEquals("wrong processId", "367100000000079", resp.getProcessId().toString()); +    assertEquals("wrong resp size", 1, resp.getPersonResult().size()); + +    RegisterResult persInfo = resp.getPersonResult().get(0); +    assertEquals("bPK", "UgeknNsc26lVuB7U/uYGVmWtnnA=", persInfo.getBpk()); +    assertEquals("dateOfBirth", eidasDataFirst.getDateOfBirth(), persInfo.getDateOfBirth()); +    assertEquals("familyName", eidasDataFirst.getFamilyName(), persInfo.getFamilyName()); +    assertEquals("givenName", eidasDataFirst.getGivenName(), persInfo.getGivenName()); +    assertEquals("placeOfBirth", "Hintergigritzpotschn", persInfo.getPlaceOfBirth()); +    assertEquals("birthName", "XXXvon Heuburg", persInfo.getBirthName()); +    assertEquals("num. stored eIDAS identifiers", 2, persInfo.getPseudonym().size()); +    assertEquals("stored eIDAS identifiers", "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit", +        persInfo.getPseudonym().get(0)); +    assertEquals("stored eIDAS identifiers", +        "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit_second_one", +        persInfo.getPseudonym().get(1)); + +    // validate request +    assertEquals("wrong number of req.", 1, zmrReq.getAllValues().size()); +    assertNotNull("Personensuche req.", zmrReq.getValue().getPersonSuchenRequest()); +    checkBasicRequestParameters(zmrReq.getValue(), PROCESS_TASK_SEARCH, processId, "jUnit123456"); +    PersonSuchenRequest pSuche = zmrReq.getValue().getPersonSuchenRequest();    +    assertEquals("req. Municipality", addressInfo.getMunicipality(), pSuche.getPostAdresse().getGemeinde());     +    assertEquals("req. Postleitzahl", addressInfo.getPostleitzahl(), pSuche.getPostAdresse().getPostleitzahl()); +    assertNull("req. Village", pSuche.getPostAdresse().getOrtschaft()); +    assertNull("req. Number", pSuche.getPostAdresse().getZustelladresse()); +     +  } +   +   +  @Test +  @SneakyThrows    public void updateProcessNoLatestVersionResult() {      BigInteger processId = new BigInteger(RandomStringUtils.randomNumeric(6)); @@ -777,13 +940,19 @@ public class ZmrClientTest {      assertEquals("2 req. tech. Ref. date", "2020-02-05T13:07:06.311",           secondpSuche.getPersonReferenz().getTechnisch().getLetzteAenderung().toString());   -    assertEquals("eidas Docs. size", 3, secondpSuche.getEidasIdentitaetAnlage().size()); +    assertEquals("eidas Docs. size", 6, secondpSuche.getEidasIdentitaetAnlage().size());      checkEidasDocumentAdd(secondpSuche.getEidasIdentitaetAnlage(),          "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", cc, eidasData.getPlaceOfBirth());      checkEidasDocumentAdd(secondpSuche.getEidasIdentitaetAnlage(),          "http://eidas.europa.eu/attributes/naturalperson/BirthName", cc, eidasData.getBirthName());      checkEidasDocumentAdd(secondpSuche.getEidasIdentitaetAnlage(), -        "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", cc, eidasData.getPseudonym()); +        "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", cc, eidasData.getPseudonym());     +    checkEidasDocumentAdd(secondpSuche.getEidasIdentitaetAnlage(), +        "http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName", cc, eidasData.getGivenName()); +    checkEidasDocumentAdd(secondpSuche.getEidasIdentitaetAnlage(), +        "http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName", cc, eidasData.getFamilyName()); +    checkEidasDocumentAdd(secondpSuche.getEidasIdentitaetAnlage(), +        "http://eidas.europa.eu/attributes/naturalperson/DateOfBirth", cc, eidasData.getDateOfBirth());      // validate state @@ -947,8 +1116,7 @@ public class ZmrClientTest {      assertEquals("eidas Docs. size", 1, secondpSuche.getEidasIdentitaetAnlage().size());      checkEidasDocumentAdd(secondpSuche.getEidasIdentitaetAnlage(),          "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", cc, eidasData.getPseudonym()); -     -     +              // validate state      assertNotNull("no ZMR response", resp);      assertEquals("wrong processId", "366200000000082", resp.getProcessId().toString()); @@ -978,7 +1146,7 @@ public class ZmrClientTest {      return req;    } - +      private void addIfAvailable(List<EidasSuchdatenType> eidasSuchdaten,        String cc, String attrName, String attrValue) {      if (StringUtils.isNotEmpty(attrValue)) { diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/AlternativeSearchTaskWithRegisterTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/AlternativeSearchTaskWithRegisterTest.java index 63266cf6..3814c632 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/AlternativeSearchTaskWithRegisterTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/AlternativeSearchTaskWithRegisterTest.java @@ -35,7 +35,7 @@ import org.junit.Test;  import org.junit.runner.RunWith;  import org.mockito.ArgumentCaptor;  import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.Mockito;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.mock.web.MockHttpServletRequest;  import org.springframework.mock.web.MockHttpServletResponse; @@ -49,12 +49,13 @@ import org.springframework.web.context.request.ServletRequestAttributes;  import com.github.skjolber.mockito.soap.SoapServiceRule;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient;  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.MatchedPersonResult;  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.EidPostProcessingException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; @@ -70,6 +71,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils;  import at.gv.bmi.namespace.zmr_su.base._20040201.RequestType;  import at.gv.bmi.namespace.zmr_su.base._20040201.ResponseType;  import at.gv.bmi.namespace.zmr_su.base._20040201_.ServicePort; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.EidasIdentitaetAnlageType;  import at.gv.bmi.namespace.zmr_su.zmr._20040201.EidasSuchdatenType;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; @@ -407,7 +409,10 @@ public class AlternativeSearchTaskWithRegisterTest {      when(zmrMock.service(zmrReq.capture(), any()))          .thenReturn(loadResponseFromFile("/data/zmr/seq_1-8_search_with_personalId_only_resp.xml"))          .thenThrow(new RuntimeException("This request is not needed any more")); - +     +    Mockito.when(ernpClient.searchWithPersonIdentifier(any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +          // execute task      TaskExecutionException exception = assertThrows(TaskExecutionException.class,          () -> task.execute(pendingReq, executionContext)); @@ -470,6 +475,13 @@ public class AlternativeSearchTaskWithRegisterTest {          .thenReturn(loadResponseFromFile("/data/zmr/seq_3-8_kitt_get_latest_version_resp.xml"))          .thenThrow(new RuntimeException("This request is not needed any more")); +    Mockito.when(ernpClient.searchWithPersonIdentifier(any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(any(), any(), any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); +          // execute task      task.execute(pendingReq, executionContext); @@ -498,7 +510,16 @@ public class AlternativeSearchTaskWithRegisterTest {      assertNotNull("PersonAender KITT req.", zmrReq.getAllValues().get(2).getPersonAendernRequest());      checkBasicRequestParameters(zmrReq.getAllValues().get(2), ZmrClientTest.PROCESS_TASK_UPDATE,          new BigInteger("367100000000079"), "jUnit123456"); - +     +    assertEquals("wrong number of eIDAS Docs to Add", 4,  +        zmrReq.getAllValues().get(2).getPersonAendernRequest().getEidasIdentitaetAnlage().size()); +    checkEidasDocumentAdd(zmrReq.getAllValues().get(2).getPersonAendernRequest().getEidasIdentitaetAnlage(), +        "http://eidas.europa.eu/attributes/naturalperson/DateOfBirth", "DE", "1994-12-31"); +    checkEidasDocumentAdd(zmrReq.getAllValues().get(2).getPersonAendernRequest().getEidasIdentitaetAnlage(), +        "http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName", "DE", "XXXKlaus - Maria"); +    checkEidasDocumentAdd(zmrReq.getAllValues().get(2).getPersonAendernRequest().getEidasIdentitaetAnlage(), +        "http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName", "DE", "XXXvon Brandenburg"); +          assertNotNull("Personensuche KITT req.", zmrReq.getAllValues().get(3).getPersonSuchenRequest());      checkBasicRequestParameters(zmrReq.getAllValues().get(3), ZmrClientTest.PROCESS_TASK_SEARCH,          new BigInteger("367100000000079"), "jUnit123456"); @@ -549,6 +570,15 @@ public class AlternativeSearchTaskWithRegisterTest {          .thenReturn(loadResponseFromFile("/data/zmr/seq_3-10_kitt_update_resp.xml"))          .thenThrow(new RuntimeException("This request is not needed any more")); +    Mockito.when(ernpClient.searchWithPersonIdentifier(any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchCountrySpecific(any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(any(), any(), any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); +          // execute task      task.execute(pendingReq, executionContext); @@ -636,6 +666,9 @@ public class AlternativeSearchTaskWithRegisterTest {          .thenReturn(loadResponseFromFile("/data/zmr/empty_zmr_result.xml"))          .thenThrow(new RuntimeException("This request is not needed any more")); +    Mockito.when(ernpClient.searchWithPersonIdentifier(any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +          // execute task      task.execute(pendingReq, executionContext); @@ -697,6 +730,13 @@ public class AlternativeSearchTaskWithRegisterTest {          .thenReturn(loadResponseFromFile("/data/zmr/search_with_personalId_only_resp_moreThanOne.xml"))          .thenThrow(new RuntimeException("This request is not needed any more")); +    Mockito.when(ernpClient.searchWithPersonIdentifier(any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(any(), any(), any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); +          // execute task      TaskExecutionException exception = assertThrows(TaskExecutionException.class,          () -> task.execute(pendingReq, executionContext)); @@ -769,6 +809,14 @@ public class AlternativeSearchTaskWithRegisterTest {          .thenReturn(loadResponseFromFile("/data/zmr/empty_zmr_result.xml"))          .thenThrow(new RuntimeException("This request is not needed any more")); +    Mockito.when(ernpClient.searchWithPersonIdentifier("7cEYasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit", "DE")) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchCountrySpecific(any(), any())) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); +     +          // execute task      task.execute(pendingReq, executionContext); @@ -777,6 +825,9 @@ public class AlternativeSearchTaskWithRegisterTest {      assertNull("final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq));      assertEquals("wrong executionContextFlag 'alternative eIDAS result'", true,          executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.25", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON));     +          // validate request @@ -971,5 +1022,21 @@ public class AlternativeSearchTaskWithRegisterTest {    } +  private void checkEidasDocumentAdd(List<EidasIdentitaetAnlageType> list, String type, String cc, String value) { +    Optional<EidasIdentitaetAnlageType> eidasDoc = list.stream() +        .filter(el -> type.equals(el.getEidasArt())) +        .findFirst(); + +    assertTrue("eidas doc: " + type, eidasDoc.isPresent()); +    assertEquals("eIDAS docType", type, eidasDoc.get().getEidasArt()); +    assertEquals("eIDAS docValue", value, eidasDoc.get().getEidasWert()); +    assertEquals("eIDAS docCC", cc, eidasDoc.get().getStaatscode2()); +  } +   +  @NotNull +  private ErnpRegisterResult emptyErnpRegisterResult() { +    return new ErnpRegisterResult(Collections.emptyList()); +  } +  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java index e3757c0d..dbcc62dc 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java @@ -133,6 +133,7 @@ public class CreateIdentityLinkTaskEidNewTest {    private static ObjectMapper mapper = new ObjectMapper();    private AuthenticationResponse response; +  private MatchedPersonResult matchingInfos;    @Rule    public final SoapServiceRule soap = SoapServiceRule.newInstance(); @@ -168,7 +169,14 @@ public class CreateIdentityLinkTaskEidNewTest {      final SimpleEidasData eidData = eidPostProcessor.postProcess(eidasAttributes);          MatchingTaskUtils.storeInitialEidasData(pendingReq, eidData); -    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, null); +    matchingInfos = MatchedPersonResult.builder() +        .bpk(RandomStringUtils.randomAlphabetic(5)) +        .givenName(eidData.getGivenName()) +        .familyName(eidData.getFamilyName()) +        .dateOfBirth(eidData.getDateOfBirth()) +        .countryCode(eidData.getCitizenCountryCode()) +        .build();         +    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, matchingInfos);      pendingReq.setSpConfig(oaParam);      pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue()); @@ -187,13 +195,23 @@ public class CreateIdentityLinkTaskEidNewTest {      //initialize test      response = buildDummyAuthResponse(true);      pendingReq.getSessionData(AuthProcessDataWrapper.class) -        .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);     -    MatchingTaskUtils.storeInitialEidasData(pendingReq, eidPostProcessor.postProcess( -        convertEidasAttrToSimpleMap(response.getAttributes().getAttributeMap()))); +        .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response); +    SimpleEidasData eidData = eidPostProcessor.postProcess( +        convertEidasAttrToSimpleMap(response.getAttributes().getAttributeMap())); +    MatchingTaskUtils.storeInitialEidasData(pendingReq, eidData); +     +    matchingInfos = MatchedPersonResult.builder() +        .bpk(RandomStringUtils.randomAlphabetic(5)) +        .givenName(eidData.getGivenName()) +        .familyName(eidData.getFamilyName()) +        .dateOfBirth(eidData.getDateOfBirth()) +        .countryCode(eidData.getCitizenCountryCode()) +        .build();         +    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, matchingInfos);      String vsz = RandomStringUtils.randomNumeric(10);      when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(vsz); -    val signContentResp = new SignContentResponseType(); +    SignContentResponseType signContentResp = new SignContentResponseType();      final SignContentEntry signContentEntry = new SignContentEntry();      signContentEntry.setValue(RandomStringUtils.randomAlphanumeric(10));      signContentResp.getOut().add(signContentEntry); @@ -251,7 +269,7 @@ public class CreateIdentityLinkTaskEidNewTest {      verify(szrMock, times(1)).getStammzahlEncrypted(argument4.capture(), argument5.capture());      Boolean param5 = argument5.getValue(); -    Assert.assertTrue("insertERnP flag", param5); +    Assert.assertFalse("insertERnP flag", param5);      PersonInfoType person = argument4.getValue();      Assert.assertEquals("FamilyName",          response.getAttributes().getAttributeValuesByFriendlyName("FamilyName").getFirstValue( @@ -267,23 +285,9 @@ public class CreateIdentityLinkTaskEidNewTest {              .toString().split("T")[0],          person.getPerson().getDateOfBirth()); -    Assert.assertEquals("PlaceOfBirth", -        response.getAttributes().getAttributeValuesByFriendlyName("PlaceOfBirth").getFirstValue( -            response.getAttributes().getDefinitionsByFriendlyName("PlaceOfBirth").iterator().next()), -        person.getPerson().getPlaceOfBirth()); -    Assert.assertEquals("BirthName", -        response.getAttributes().getAttributeValuesByFriendlyName("BirthName").getFirstValue( -            response.getAttributes().getDefinitionsByFriendlyName("BirthName").iterator().next()), -        person.getPerson().getAlternativeName().getFamilyName()); - -    Assert.assertEquals("CitizenCountry", "LU", person.getTravelDocument().getIssuingCountry()); -    Assert.assertEquals("DocumentType", "ELEKTR_DOKUMENT", person.getTravelDocument().getDocumentType()); - -    Assert.assertEquals("Identifier", -        response.getAttributes().getAttributeValuesByFriendlyName("PersonIdentifier").getFirstValue( -            response.getAttributes().getDefinitionsByFriendlyName("PersonIdentifier").iterator().next()) -            .toString().split("/")[2], -        person.getTravelDocument().getDocumentNumber()); +    Assert.assertNull("PlaceOfBirth", person.getPerson().getPlaceOfBirth()); +    Assert.assertNull("BirthName", person.getPerson().getAlternativeName()); +    Assert.assertNull("TravelDocument", person.getTravelDocument());      // check bcBind singing request      ArgumentCaptor<Boolean> argument1 = ArgumentCaptor.forClass(Boolean.class); @@ -329,27 +333,16 @@ public class CreateIdentityLinkTaskEidNewTest {      //initialize test      String vsz = RandomStringUtils.randomNumeric(10);      when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(vsz); -    val signContentResp = new SignContentResponseType(); +    SignContentResponseType signContentResp = new SignContentResponseType();      final SignContentEntry signContentEntry = new SignContentEntry();      signContentEntry.setValue(RandomStringUtils.randomAlphanumeric(10));      signContentResp.getOut().add(signContentEntry);      when(szrMock.signContent(any(), any(), any())).thenReturn(signContentResp); -      String randomTestSp = RandomStringUtils.randomAlphabetic(10);      String bindingPubKey = RandomStringUtils.randomAlphabetic(10);      pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); - -    MatchedPersonResult matchingInfos = MatchedPersonResult.builder() -        .bpk(RandomStringUtils.randomAlphabetic(5)) -        .givenName(RandomStringUtils.randomAlphabetic(5)) -        .familyName(RandomStringUtils.randomAlphabetic(5)) -        .dateOfBirth(RandomStringUtils.randomAlphabetic(5)) -        .countryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase()) -        .build();         -    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, matchingInfos); -      pendingReq.setRawDataToTransaction(MsEidasNodeConstants.EID_BINDING_PUBLIC_KEY_NAME, bindingPubKey); @@ -467,7 +460,7 @@ public class CreateIdentityLinkTaskEidNewTest {      verify(szrMock, times(1)).getStammzahlEncrypted(argument4.capture(), argument5.capture());      Boolean param5 = argument5.getValue(); -    Assert.assertTrue("insertERnP flag", param5); +    Assert.assertFalse("insertERnP flag", param5);      PersonInfoType person = argument4.getValue();      Assert.assertEquals("FamilyName",          response.getAttributes().getAttributeValuesByFriendlyName("FamilyName").getFirstValue( @@ -485,15 +478,7 @@ public class CreateIdentityLinkTaskEidNewTest {      Assert.assertNull("PlaceOfBirth", person.getPerson().getPlaceOfBirth());      Assert.assertNull("BirthName", person.getPerson().getAlternativeName()); - -    Assert.assertEquals("CitizenCountry", "LU", person.getTravelDocument().getIssuingCountry()); -    Assert.assertEquals("DocumentType", "ELEKTR_DOKUMENT", person.getTravelDocument().getDocumentType()); - -    Assert.assertEquals("Identifier", -        response.getAttributes().getAttributeValuesByFriendlyName("PersonIdentifier").getFirstValue( -            response.getAttributes().getDefinitionsByFriendlyName("PersonIdentifier").iterator().next()) -            .toString().split("/")[2], -        person.getTravelDocument().getDocumentNumber()); +    Assert.assertNull("TravelDocument", person.getTravelDocument());    } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java index 7513501e..4986d5a7 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskTest.java @@ -105,6 +105,7 @@ public class CreateIdentityLinkTaskTest {    private DummySpConfiguration oaParam;    private SZR szrMock; +  private MatchedPersonResult matchingInfos;    private AuthenticationResponse response;    private Map<String, String> spConfig; @@ -143,7 +144,14 @@ public class CreateIdentityLinkTaskTest {      pendingReq.getSessionData(AuthProcessDataWrapper.class)          .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response); -    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, null); +    matchingInfos = MatchedPersonResult.builder() +        .bpk(RandomStringUtils.randomAlphabetic(5)) +        .givenName(eidData.getGivenName()) +        .familyName(eidData.getFamilyName()) +        .dateOfBirth(eidData.getDateOfBirth()) +        .countryCode(eidData.getCitizenCountryCode()) +        .build();         +    MatchingTaskUtils.storeFinalMatchingResult(pendingReq, matchingInfos);      pendingReq.setSpConfig(oaParam);      pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue()); @@ -447,41 +455,6 @@ public class CreateIdentityLinkTaskTest {            authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.BPK_NAME));    } -  @Test -  public void buildDummyIdl() throws Exception { -    //initialize test -    String randomTestSp = RandomStringUtils.randomAlphabetic(10); -    pendingReq.setRawDataToTransaction(MsEidasNodeConstants.DATA_REQUESTERID, randomTestSp); - -    basicConfig.putConfigValue("eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution", "true"); - - -    //perform test -    task.execute(pendingReq, executionContext); - - -    //validate state -    // check if pendingRequest was stored -    IRequest storedPendingReq = requestStorage.getPendingRequest(pendingReq.getPendingRequestId()); -    Assert.assertNotNull("pendingReq not stored", storedPendingReq); - -    //check data in session -    final AuthProcessDataWrapper authProcessData = storedPendingReq.getSessionData(AuthProcessDataWrapper.class); -    Assert.assertNotNull("AuthProcessData", authProcessData); -    Assert.assertNull("eidasBind", authProcessData.getGenericDataFromSession(Constants.EIDAS_BIND, String.class)); - -    String authBlock = authProcessData.getGenericDataFromSession(Constants.SZR_AUTHBLOCK, String.class); -    Assert.assertNull("AuthBlock", authBlock); - -    Assert.assertFalse("EID process", authProcessData.isEidProcess()); -    Assert.assertTrue("foreigner process", authProcessData.isForeigner()); -    Assert.assertEquals("EID-ISSUING_NATION", "LU", -        authProcessData.getGenericDataFromSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, String.class)); - -    Assert.assertNotNull("IDL", authProcessData.getIdentityLink()); - -  } -    private void setSzrResponseIdentityLink(String responseXmlPath) throws JAXBException, SZRException_Exception {      final JAXBContext jaxbContext = JAXBContext          .newInstance(szrservices.ObjectFactory.class, org.w3._2001._04.xmldsig_more.ObjectFactory.class, diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateNewErnpEntryTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateNewErnpEntryTaskTest.java new file mode 100644 index 00000000..985a5e14 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateNewErnpEntryTaskTest.java @@ -0,0 +1,198 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; + +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.lang3.RandomStringUtils; +import org.jetbrains.annotations.NotNull; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +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; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult; +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.exception.WorkflowException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateNewErnpEntryTask; +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.EaafStorageException; +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; +import lombok.SneakyThrows; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { +    "/SpringTest-context_tasks_test.xml", +    "/SpringTest-context_basic_mapConfig.xml" +}) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) +public class CreateNewErnpEntryTaskTest { + +  CreateNewErnpEntryTask task;  +   +  @Mock ErnpRestClient ernpClient; +   +  final ExecutionContext executionContext = new ExecutionContextImpl(); +  private TestRequestImpl pendingReq; +   +  /** +   * jUnit test set-up. +   */ +  @Before +  public void setUp() throws URISyntaxException, EaafStorageException {     +    task = new CreateNewErnpEntryTask(ernpClient); +     +    MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    MockHttpServletResponse httpResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + +    pendingReq = new TestRequestImpl(); +    pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); +     +  } +   +   +  @Test +  @SneakyThrows +  public void missingEidasData() {     +    Mockito.when(ernpClient.add(any())) +        .thenThrow(new IllegalStateException("add ERnP entry should not be neccessary")); +             +    TaskExecutionException error = assertThrows("wrong exception", TaskExecutionException.class,  +        () -> task.execute(pendingReq, executionContext));  +     +    assertEquals("wrong pendingRequestId", pendingReq.getPendingRequestId(), error.getPendingRequestID()); +    assertTrue("Wrong exception", (error.getOriginalException() instanceof WorkflowException)); +    assertTrue("Wrong flag 'manualFixNeeded'", +        ((WorkflowException) error.getOriginalException()).isRequiresManualFix()); +     +  } +   +  @Test +  @SneakyThrows +  public void noErnpResponse() {       +    SimpleEidasData input = buildInputData();             +    Mockito.when(ernpClient.add(input)) +        .thenReturn(ernpRegisterResult(Arrays.asList())); +             +    TaskExecutionException error = assertThrows("wrong exception", TaskExecutionException.class,  +        () -> task.execute(pendingReq, executionContext));  +     +    assertEquals("wrong pendingRequestId", pendingReq.getPendingRequestId(), error.getPendingRequestID()); +    assertTrue("Wrong exception", (error.getOriginalException() instanceof WorkflowException)); +    assertTrue("Wrong flag 'manualFixNeeded'", +        ((WorkflowException) error.getOriginalException()).isRequiresManualFix()); +     +  } +    +  @Test +  @SneakyThrows +  public void moreThanOneErnpResponse() {      +    String bpk = RandomStringUtils.randomAlphabetic(5);   +    SimpleEidasData input = buildInputData();             +    Mockito.when(ernpClient.add(input)) +        .thenReturn(ernpRegisterResult(Arrays.asList(buildErnpResultEntry(input, bpk), buildRandomResultEntry()))); +             +    TaskExecutionException error = assertThrows("wrong exception", TaskExecutionException.class,  +        () -> task.execute(pendingReq, executionContext));  +     +    assertEquals("wrong pendingRequestId", pendingReq.getPendingRequestId(), error.getPendingRequestID()); +    assertTrue("Wrong exception", (error.getOriginalException() instanceof WorkflowException)); +    assertTrue("Wrong flag 'manualFixNeeded'", +        ((WorkflowException) error.getOriginalException()).isRequiresManualFix()); +     +  } +   +  @Test +  @SneakyThrows +  public void insertErnpSuccess() { +    String bpk = RandomStringUtils.randomAlphabetic(5);   +    SimpleEidasData input = buildInputData();             +    Mockito.when(ernpClient.add(input)) +        .thenReturn(ernpRegisterResult(Arrays.asList(buildErnpResultEntry(input, bpk)))); +         +    // perform test +    task.execute(pendingReq, executionContext); +         +    // validate state +    MatchedPersonResult result = MatchingTaskUtils.getFinalMatchingResult(pendingReq); +    assertNotNull("no matching result", result); +    assertEquals("familyname", input.getFamilyName(), result.getFamilyName()); +    assertEquals("givenyname", input.getGivenName(), result.getGivenName()); +    assertEquals("dateOfBirth", input.getDateOfBirth(), result.getDateOfBirth()); +    assertEquals("bpk", bpk, result.getBpk()); +    assertEquals("countryCode", input.getCitizenCountryCode(), result.getCountryCode()); +     +  } + + +  @NotNull +  private ErnpRegisterResult ernpRegisterResult(List<RegisterResult> registerResult) { +    return new ErnpRegisterResult(registerResult); +     +  } + +  private RegisterResult buildErnpResultEntry(SimpleEidasData input, String bpk) { +    return buildErnpResultEntry(input.getFamilyName(), input.getGivenName(), input.getDateOfBirth(), bpk); +     +  } +   +  private RegisterResult buildRandomResultEntry() { +    return buildErnpResultEntry(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5),  +        RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)); +     +  } +   +  private RegisterResult buildErnpResultEntry(String familyName, String givenName, String birthday, String bpk) { +    return RegisterResult.builder() +        .bpk(bpk) +        .dateOfBirth(birthday) +        .givenName(givenName) +        .familyName(familyName) +        .build(); +     +  } +   +  private SimpleEidasData buildInputData() throws EaafStorageException { +    String cc = RandomStringUtils.randomAlphabetic(5).toUpperCase(); +    String pseudonym = RandomStringUtils.randomAlphabetic(5); +    String familyName = RandomStringUtils.randomAlphabetic(5);     +    String givenName = RandomStringUtils.randomAlphabetic(5); +    String birthday = RandomStringUtils.randomNumeric(4) + "-"  +        + RandomStringUtils.randomNumeric(2) + "-" + RandomStringUtils.randomNumeric(2); +               +    SimpleEidasData input = SimpleEidasData.builder()         +        .familyName(familyName) +        .givenName(givenName) +        .dateOfBirth(birthday) +        .personalIdentifier(cc + "/AT/" + pseudonym) +        .pseudonym(pseudonym) +        .citizenCountryCode(cc) +        .build();     +    MatchingTaskUtils.storeInitialEidasData(pendingReq, input); +    return input; +     +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java index f17f69c3..ff994061 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/GenerateOtherLoginMethodGuiTaskTest.java @@ -1,15 +1,13 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks; -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; -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; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; -import lombok.SneakyThrows; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.UnsupportedEncodingException; +import java.text.MessageFormat; +import java.util.Locale; +  import org.apache.commons.lang3.RandomStringUtils;  import org.junit.Assert;  import org.junit.Before; @@ -26,12 +24,17 @@ import org.springframework.test.context.web.WebAppConfiguration;  import org.springframework.web.context.request.RequestContextHolder;  import org.springframework.web.context.request.ServletRequestAttributes; -import java.io.UnsupportedEncodingException; -import java.text.MessageFormat; -import java.util.Locale; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +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; +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; +import lombok.SneakyThrows;  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration(locations = { @@ -82,8 +85,9 @@ public class GenerateOtherLoginMethodGuiTaskTest {    @Test    @SneakyThrows    public void jsonResponse() throws TaskExecutionException, UnsupportedEncodingException { - +    String reason = RandomStringUtils.randomAlphabetic(5);      executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); +    executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, reason);      httpReq.addHeader("Accept", "application/json");      task.execute(pendingReq, executionContext); @@ -98,20 +102,44 @@ public class GenerateOtherLoginMethodGuiTaskTest {      assertNotNull("response body is null", json);      assertNotNull("advancedMatchFailed", json.get(Constants.HTML_FORM_ADVANCED_MATCHING_FAILED));      assertTrue("advancedMatchFailed", json.get(Constants.HTML_FORM_ADVANCED_MATCHING_FAILED).asBoolean()); - +    assertNotNull("advancedMatchingFailedReason", json.get(Constants.HTML_FORM_ADVANCED_MATCHING_FAILED_REASON)); +    assertEquals("advancedMatchingFailedReason", reason,  +        json.get(Constants.HTML_FORM_ADVANCED_MATCHING_FAILED_REASON).asText()); +        }    @Test    public void advancedMatchingFailedMsg() throws TaskExecutionException, UnsupportedEncodingException { -      executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);      task.execute(pendingReq, executionContext); +         +    String html = doBasicValidation(); +    Assert.assertTrue("Missing eIDAS infos", +        html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM, SelectedLoginMethod.ADD_ME_AS_NEW))); +    Assert.assertTrue("missing errorfield", +        html.contains("<div id=\"matchingError\"")); +     +  } -    doBasicValidation(); +  @Test +  public void advancedMatchingFailedMsgWithDetails() throws TaskExecutionException, UnsupportedEncodingException { +    String reason = RandomStringUtils.randomAlphabetic(5); +    executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); +    executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, reason); +     +    task.execute(pendingReq, executionContext); +    String html = doBasicValidation(); +    Assert.assertTrue("Missing eIDAS infos", +        html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM, SelectedLoginMethod.ADD_ME_AS_NEW))); +    Assert.assertTrue("missing errorfield", +        html.contains("<div id=\"matchingError\"")); +    Assert.assertTrue("missing errorfield", +        html.contains(reason)); +        } - +      @Test    public void validHtmlResponseWithOutLocale() throws TaskExecutionException, UnsupportedEncodingException { @@ -153,7 +181,7 @@ public class GenerateOtherLoginMethodGuiTaskTest {    } -  private void doBasicValidation() throws UnsupportedEncodingException { +  private String doBasicValidation() throws UnsupportedEncodingException {      Assert.assertEquals("Wrong http StatusCode", 200, httpResp.getStatus());      Assert.assertEquals("Wrong http ContentType", "text/html;charset=UTF-8", httpResp.getContentType()); @@ -165,11 +193,15 @@ public class GenerateOtherLoginMethodGuiTaskTest {          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))); - +    Assert.assertTrue("Missing eIDAS infos", +        html.contains(MessageFormat.format(TEST_PATTER_REQ_PARAM, SelectedLoginMethod.EIDAS_LOGIN))); +              Assert.assertTrue("No language selector with pendingRequestId",          html.contains("/otherLoginMethod?pendingid=" + pendingReq.getPendingRequestId()));      Assert.assertTrue("No country-selection form",          html.contains("<form method=\"post\" action=\"/otherLoginMethod\">")); +     +    return html;    }  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java index e5ba2e07..74ac065e 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskTest.java @@ -23,15 +23,59 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +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 static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; + +import java.math.BigInteger; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.RandomStringUtils; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.IZmrClient;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient.ZmrRegisterResult;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;  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.*; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException; +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.exception.ZmrCommunicationException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.CountrySpecificDetailSearchProcessor;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.GenericEidProcessor;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.ICcSpecificEidProcessingService; @@ -52,36 +96,6 @@ import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;  import eu.eidas.auth.commons.attribute.PersonType;  import eu.eidas.auth.commons.light.impl.LightRequest;  import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; -import org.apache.commons.lang3.RandomStringUtils; -import org.jetbrains.annotations.NotNull; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.annotation.DirtiesContext.ClassMode; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.xml.namespace.QName; -import java.math.BigInteger; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq;  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration(locations = { @@ -166,16 +180,25 @@ public class InitialSearchTaskTest {    @DirtiesContext    public void singlePersonalIdMatchUpdateNecessary_Zmr() throws Exception {      String oldGivenName = randomAlphabetic(10); +    String placeOfBirth = randomAlphabetic(10); +    RegisterResult firstZmrResult = randomRegisterResult(oldGivenName, randomBpk, placeOfBirth);          Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE)) -        .thenReturn(zmrRegisterResult(randomRegisterResult(oldGivenName, randomBpk))); +        .thenReturn(zmrRegisterResult(firstZmrResult));      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())) -        .thenThrow(new IllegalStateException("ZMR update should not be neccessary")); +        .thenReturn(zmrRegisterResult(firstZmrResult)); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult()); +    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); @@ -186,23 +209,38 @@ public class InitialSearchTaskTest {    }    /** -   * TODO: include again if ERnP update is implementet. Maybe we can update MDS based on ERnP. -   * <p> +   *      * One match, but register update needed.     *     * @throws EidasSAuthenticationException     */ -  @Ignore    @Test    @DirtiesContext    public void singlePersonalIdMatchUpdateNecessary_Ernp() throws TaskExecutionException, EidasSAuthenticationException {      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())) +        .thenThrow(new IllegalStateException("ZMR update should not be neccessary")); +          String oldRandomGivenName = randomAlphabetic(10); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.singletonList(randomRegisterResult(oldRandomGivenName, randomBpk))); - +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(ernpRegisterResult(randomRegisterResult(oldRandomGivenName, randomBpk))); +    Mockito.when(ernpClient.searchCountrySpecific(any(), any())) +        .thenThrow(new IllegalStateException("CountrySpecific search search should not be neccessary")); +    Mockito.when(ernpClient.searchWithMds(any(), any(), any(), any())) +        .thenThrow(new IllegalStateException("MDS search should not be neccessary")); +    Mockito.when(ernpClient.update(any(), any())) +        .thenReturn(ernpRegisterResult(RegisterResult.builder() +            .bpk(randomBpk) +            .dateOfBirth(randomBirthDate) +            .givenName(randomGivenName) +            .familyName(randomFamilyName) +            .build())); +          // execute test      task.execute(pendingReq, executionContext); @@ -210,11 +248,8 @@ public class InitialSearchTaskTest {      checkMatchingSuccessState(pendingReq, randomBpk, randomFamilyName, randomGivenName, randomBirthDate, DE);    } -  @NotNull -  private ZmrSoapClient.ZmrRegisterResult emptyZmrRegisterResult() { -    return new ZmrRegisterResult(Collections.emptyList(), generateRandomProcessId()); -  } +      /**     * Two matches by PersonalId found in ZMR     * @@ -226,8 +261,8 @@ public class InitialSearchTaskTest {      String newRandomGivenName = randomAlphabetic(10);      Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE))          .thenReturn(new ZmrRegisterResult(Arrays.asList(randomRegisterResult(), randomRegisterResult(newRandomGivenName, randomBpk)), generateRandomProcessId())); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.emptyList()); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult());      // execute task      TaskExecutionException exception = assertThrows(TaskExecutionException.class, @@ -251,8 +286,8 @@ public class InitialSearchTaskTest {    public void withErrorFromZmr() throws EidasSAuthenticationException {      Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE))          .thenThrow(new ZmrCommunicationException("jUnit ZMR error", null)); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.emptyList()); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult());      // execute task      TaskExecutionException exception = assertThrows(TaskExecutionException.class, @@ -277,8 +312,9 @@ public class InitialSearchTaskTest {      Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE))          .thenReturn(emptyZmrRegisterResult());      String newRandomGivenName = randomAlphabetic(10); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Arrays.asList(randomRegisterResult(), randomRegisterResult(newRandomGivenName, randomBpk))); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(ernpRegisterResult( +            Arrays.asList(randomRegisterResult(), randomRegisterResult(newRandomGivenName, randomBpk))));      // execute task      TaskExecutionException exception = assertThrows(TaskExecutionException.class, @@ -301,9 +337,8 @@ public class InitialSearchTaskTest {    public void multiPersonalIdMatch_ErnpAndZmr() throws EidasSAuthenticationException {      Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE))          .thenReturn(zmrRegisterResult(randomRegisterResult())); -    String newRandomGivenName = randomAlphabetic(10); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.singletonList(randomRegisterResult())); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(ernpRegisterResult(randomRegisterResult()));      // execute task      TaskExecutionException exception = assertThrows(TaskExecutionException.class, @@ -324,8 +359,13 @@ public class InitialSearchTaskTest {    public void singlePersonalIdMatchNoUpdate_Ernp() throws Exception {      Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE))          .thenReturn(emptyZmrRegisterResult()); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.singletonList(randomRegisterResult())); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(ernpRegisterResult(randomRegisterResult()));   +     +    Mockito.when(zmrClient.update(any(), any(), any())) +        .thenThrow(new IllegalStateException("ZMR update 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); @@ -342,10 +382,13 @@ public class InitialSearchTaskTest {    public void singlePersonalIdMatchNoUpdate_Zmr() throws Exception {      Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE))          .thenReturn(zmrRegisterResult(randomRegisterResult())); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.emptyList()); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult()); +          Mockito.when(zmrClient.update(any(), any(), any()))          .thenThrow(new IllegalStateException("ZMR update 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); @@ -394,9 +437,17 @@ public class InitialSearchTaskTest {      Mockito.when(zmrClient.searchWithMds(any(), any(), any(), any(), any()))          .thenThrow(new IllegalStateException("MDS search should not be neccessary")); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.emptyList()); - +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchCountrySpecific(any(), eq(DE))) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(any(), any(), any(), eq(DE))) +        .thenThrow(new IllegalStateException("ERnP MDS search should not be neccessary")); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); +    Mockito.when(ernpClient.add(any())) +        .thenThrow(new IllegalStateException("ERnP add-entity should not be neccessary")); +          // execute test      task.execute(pendingReq1, executionContext); @@ -444,8 +495,12 @@ public class InitialSearchTaskTest {      Mockito.when(zmrClient.searchCountrySpecific(eq(zmrProcessId), any(PersonSuchenRequest.class), eq(DE)))          .thenReturn(new ZmrRegisterResult(Arrays.asList(randomResult1, randomResult2), zmrProcessId)); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.emptyList()); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchCountrySpecific(any(), eq(DE))) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary"));      // execute task      TaskExecutionException exception = assertThrows(TaskExecutionException.class, @@ -459,6 +514,89 @@ public class InitialSearchTaskTest {    }    /** +   * Multiple matches found in ZMR and ERnP by country specifics. +   */ +  @Test +  @DirtiesContext +  public void multiplePersonFindWithCountySpecifics_ZmrAndErnp() throws Exception { +    final AuthenticationResponse response = buildDummyAuthResponseDE(randomGivenName, randomFamilyName, +        randomPersonalIdentifier_DE, +        randomBirthDate, randomPlaceOfBirth, randomBirthName); +    TestRequestImpl pendingReq1 = new TestRequestImpl(); +    pendingReq1.getSessionData(AuthProcessDataWrapper.class) +        .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response); + +    BigInteger zmrProcessId = generateRandomProcessId(); +    Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE)) +        .thenReturn(new ZmrRegisterResult(Collections.emptyList(), zmrProcessId)); +    RegisterResult randomResult1 = RegisterResult.builder() +        .bpk(randomBpk) +        .pseudonym(Collections.singletonList(randomPseudonym)) +        .givenName(randomGivenName) +        .familyName(randomFamilyName) +        .dateOfBirth(randomBirthDate) +        .placeOfBirth(randomPlaceOfBirth) +        .birthName(randomBirthName) +        .build(); +    Mockito.when(zmrClient.searchCountrySpecific(eq(zmrProcessId), any(PersonSuchenRequest.class), eq(DE))) +        .thenReturn(new ZmrRegisterResult(Arrays.asList(randomResult1), zmrProcessId)); + +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchCountrySpecific(any(), eq(DE))) +        .thenReturn(ernpRegisterResult(randomRegisterResult())); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); + +    // execute task +    TaskExecutionException exception = assertThrows(TaskExecutionException.class, +        () -> task.execute(pendingReq1, executionContext)); + +    // validate state +    assertTrue("Wrong exception", (exception.getOriginalException() instanceof WorkflowException)); +    assertTrue("Wrong flag 'manualFixNeeded'", +        ((WorkflowException) exception.getOriginalException()).isRequiresManualFix()); + +  } +   +  /** +   * Multiple matches found in ERnP by country specifics. +   */ +  @Test +  @DirtiesContext +  public void multiplePersonFindWithCountySpecifics_Ernp() throws Exception { +    final AuthenticationResponse response = buildDummyAuthResponseDE(randomGivenName, randomFamilyName, +        randomPersonalIdentifier_DE, +        randomBirthDate, randomPlaceOfBirth, randomBirthName); +    TestRequestImpl pendingReq1 = new TestRequestImpl(); +    pendingReq1.getSessionData(AuthProcessDataWrapper.class) +        .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response); + +    BigInteger zmrProcessId = generateRandomProcessId(); +    Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE)) +        .thenReturn(new ZmrRegisterResult(Collections.emptyList(), zmrProcessId)); +    Mockito.when(zmrClient.searchCountrySpecific(eq(zmrProcessId), any(PersonSuchenRequest.class), eq(DE))) +        .thenReturn(new ZmrRegisterResult(Arrays.asList(), zmrProcessId)); + +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchCountrySpecific(any(), eq(DE))) +        .thenReturn(ernpRegisterResult(Arrays.asList(randomRegisterResult(), randomRegisterResult()))); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); + +    // execute task +    TaskExecutionException exception = assertThrows(TaskExecutionException.class, +        () -> task.execute(pendingReq1, executionContext)); + +    // validate state +    assertTrue("Wrong exception", (exception.getOriginalException() instanceof WorkflowException)); +    assertTrue("Wrong flag 'manualFixNeeded'", +        ((WorkflowException) exception.getOriginalException()).isRequiresManualFix()); + +  } +   +  /**     * NO match found in ZMR and ErnP with Initial and MDS search     *     * @throws EidasSAuthenticationException @@ -480,9 +618,12 @@ public class InitialSearchTaskTest {      Mockito.when(zmrClient.update(any(), any(), any()))          .thenThrow(new IllegalStateException("ZMR update should not be neccessary")); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_EE)) -        .thenReturn(Collections.emptyList()); - +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, EE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(randomGivenName, randomFamilyName, randomBirthDate, EE)) +        .thenReturn(new ErnpRegisterResult(Collections.emptyList())); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ZMR update should not be neccessary"));      // execute task      task.execute(pendingReq, executionContext); @@ -519,10 +660,10 @@ public class InitialSearchTaskTest {      Mockito.when(zmrClient.searchWithMds(zmrProcessId, randomGivenName, randomFamilyName, randomBirthDate, EE))          .thenReturn(new ZmrRegisterResult(Collections.emptyList(), zmrProcessId)); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_EE)) -        .thenReturn(Collections.emptyList()); -    Mockito.when(ernpClient.searchWithMds(randomGivenName, randomFamilyName, randomBirthDate)) -        .thenReturn(Collections.singletonList(randomRegisterResult())); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, EE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(randomGivenName, randomFamilyName, randomBirthDate, EE)) +        .thenReturn(ernpRegisterResult(randomRegisterResult()));      // execute test      task.execute(pendingReq, executionContext); @@ -546,8 +687,14 @@ public class InitialSearchTaskTest {      Mockito.when(zmrClient.update(any(), any(), any()))          .thenThrow(new IllegalStateException("ZMR update should not be neccessary")); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)).thenReturn(Collections.emptyList()); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)).thenReturn( +        emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(randomGivenName, randomFamilyName, randomBirthDate, DE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); +          // execute test      task.execute(pendingReq, executionContext); @@ -558,6 +705,37 @@ public class InitialSearchTaskTest {    }    /** +   * Find matches with MDS search in ZMR and ERnP. +   */ +  @Test +  @DirtiesContext +  public void resultByMdsSearch_ZmrAndErnp() throws TaskExecutionException, EidasSAuthenticationException { +    BigInteger zmrProcessId = generateRandomProcessId(); +    Mockito.when(zmrClient.searchWithPersonIdentifier(null, randomPseudonym, DE)) +        .thenReturn(new ZmrRegisterResult(Collections.emptyList(), zmrProcessId)); +    Mockito.when(zmrClient.searchWithMds(zmrProcessId, randomGivenName, randomFamilyName, randomBirthDate, DE)) +        .thenReturn(zmrRegisterResult(randomRegisterResult(), zmrProcessId)); +    Mockito.when(zmrClient.update(any(), any(), any())) +        .thenThrow(new IllegalStateException("ZMR update should not be neccessary")); + +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)).thenReturn( +        emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(randomGivenName, randomFamilyName, randomBirthDate, DE)) +        .thenReturn(ernpRegisterResult(randomRegisterResult())); +    Mockito.when(ernpClient.update(any(), any())) +        .thenThrow(new IllegalStateException("ERnP update should not be neccessary")); + +     + +    // execute test +    task.execute(pendingReq, executionContext); + +    // validate state +    checkIntermediateResult(2); + +  } +   +  /**     * resultByMdsSearch     */    @Test @@ -573,10 +751,10 @@ public class InitialSearchTaskTest {      Mockito.when(zmrClient.update(any(), any(), any()))          .thenThrow(new IllegalStateException("ZMR update should not be neccessary")); -    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPersonalIdentifier_DE)) -        .thenReturn(Collections.emptyList()); -    Mockito.when(ernpClient.searchWithMds(randomGivenName, randomFamilyName, randomBirthDate)) -        .thenReturn(Arrays.asList(randomRegisterResult(), randomRegisterResult(randomBpk + "1"))); +    Mockito.when(ernpClient.searchWithPersonIdentifier(randomPseudonym, DE)) +        .thenReturn(emptyErnpRegisterResult()); +    Mockito.when(ernpClient.searchWithMds(randomGivenName, randomFamilyName, randomBirthDate, DE)) +        .thenReturn(ernpRegisterResult(Arrays.asList(randomRegisterResult(), randomRegisterResult(randomBpk + "1"))));      // execute test      task.execute(pendingReq, executionContext); @@ -587,6 +765,16 @@ public class InitialSearchTaskTest {    }    @NotNull +  private ZmrSoapClient.ZmrRegisterResult emptyZmrRegisterResult() { +    return new ZmrRegisterResult(Collections.emptyList(), generateRandomProcessId()); +  } + +  @NotNull +  private ErnpRegisterResult emptyErnpRegisterResult() { +    return new ErnpRegisterResult(Collections.emptyList()); +  } +   +  @NotNull    private ZmrRegisterResult zmrRegisterResult(RegisterResult registerResult, BigInteger processId) {      return new ZmrRegisterResult(Collections.singletonList(registerResult), processId);    } @@ -597,6 +785,16 @@ public class InitialSearchTaskTest {    }    @NotNull +  private ErnpRegisterResult ernpRegisterResult(RegisterResult registerResult) { +    return new ErnpRegisterResult(Collections.singletonList(registerResult)); +  } + +  @NotNull +  private ErnpRegisterResult ernpRegisterResult(List<RegisterResult> registerResult) { +    return new ErnpRegisterResult(registerResult); +  } +   +  @NotNull    private RegisterResult randomRegisterResult() {      return randomRegisterResult(randomGivenName, randomBpk);    } @@ -618,6 +816,18 @@ public class InitialSearchTaskTest {    }    @NotNull +  private RegisterResult randomRegisterResult(String randomGivenName, String randomBpk, String placeOfBirth) { +    return RegisterResult.builder() +        .bpk(randomBpk) +        .pseudonym(Collections.singletonList(randomPseudonym)) +        .givenName(randomGivenName) +        .familyName(randomFamilyName) +        .dateOfBirth(randomBirthDate) +        .placeOfBirth(placeOfBirth) +        .build(); +  } +   +  @NotNull    private AuthenticationResponse buildDummyAuthResponseRandomPerson() throws URISyntaxException {      return buildDummyAuthResponse(randomGivenName, randomFamilyName, DE_ST + randomPseudonym, randomBirthDate);    } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskWithRegistersTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskWithRegistersTest.java index 14ad3519..6d0e7c31 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskWithRegistersTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskWithRegistersTest.java @@ -45,8 +45,10 @@ import javax.xml.bind.JAXBException;  import javax.xml.bind.Unmarshaller;  import javax.xml.namespace.QName; +import org.apache.commons.io.IOUtils;  import org.apache.commons.lang3.RandomStringUtils;  import org.jetbrains.annotations.NotNull; +import org.junit.AfterClass;  import org.junit.Assert;  import org.junit.Before;  import org.junit.BeforeClass; @@ -54,8 +56,6 @@ import org.junit.Rule;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.mock.web.MockHttpServletRequest;  import org.springframework.mock.web.MockHttpServletResponse; @@ -69,12 +69,12 @@ import org.springframework.web.context.request.ServletRequestAttributes;  import com.github.skjolber.mockito.soap.SoapServiceRule;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient;  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.MatchedPersonResult;  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.EidPostProcessingException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; @@ -85,6 +85,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.ICcSpecificEidPr  import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService.RegisterStatusResults;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.InitialSearchTask; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.test.clients.ErnpRestClientTest;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.test.clients.ZmrClientTest;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils;  import at.gv.bmi.namespace.zmr_su.base._20040201.RequestType; @@ -103,6 +104,8 @@ import eu.eidas.auth.commons.attribute.PersonType;  import eu.eidas.auth.commons.light.impl.LightRequest;  import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;  import lombok.SneakyThrows; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer;  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration(locations = { @@ -119,14 +122,16 @@ public class InitialSearchTaskWithRegistersTest {    @Rule    public SoapServiceRule soap = SoapServiceRule.newInstance(); -  @Mock private IErnpClient ernpClient; - -  @Autowired private IZmrClient zmrClient; -  @Autowired private List<CountrySpecificDetailSearchProcessor> handlers; +  @Autowired IErnpClient ernpClient;    +  @Autowired IZmrClient zmrClient; +  @Autowired List<CountrySpecificDetailSearchProcessor> handlers; +      private RegisterSearchService registerSearchService;    private ServicePort zmrMock = null; +  private static MockWebServer mockWebServer; +      private final ICcSpecificEidProcessingService eidPostProcessor = createEidPostProcessor();    private InitialSearchTask task; @@ -144,13 +149,24 @@ public class InitialSearchTaskWithRegistersTest {          at.gv.bmi.namespace.zmr_su.zmr._20040201.ObjectFactory.class,          at.gv.bmi.namespace.zmr_su.gis._20070725.ObjectFactory.class,          at.gv.bmi.namespace.zmr_su.base._20040201.ObjectFactory.class); +     +    mockWebServer = new MockWebServer(); +    mockWebServer.start(1718); +        } +  @AfterClass +  @SneakyThrows +  public static void resetTestEnviroment() { +    mockWebServer.shutdown(); + +  }    /**     * jUnit test set-up.     */    @Before +  @SneakyThrows    public void setUp() throws URISyntaxException, EaafStorageException {      if (zmrMock == null) {        zmrMock = soap.mock(ServicePort.class, "http://localhost:1234/demozmr"); @@ -166,15 +182,18 @@ public class InitialSearchTaskWithRegistersTest {      RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));      pendingReq = new TestRequestImpl(); - +        }    /**     * One match, but register update needed +   * <p> +   * <b>Check if ZMR update request is NOT executed in case of MDS change!</b> +   * </p>     */    @Test    @DirtiesContext -  public void singlePersonalIdMatchUpdateNecessary_Zmr() throws Exception { +  public void singlePersonalIdMatchUpdateNecessary_ZmrNotDone() throws Exception {      String oldGivenName = "XXXClaus - Maria"; @@ -189,8 +208,17 @@ public class InitialSearchTaskWithRegistersTest {      // inject response      when(zmrMock.service(zmrReq.capture(), any()))          .thenReturn(loadResponseFromFile("/data/zmr/seq_1-8_search_with_personalId_only_resp.xml")) -        .thenThrow(new RuntimeException("This request is not needed any more")); +         +        //perform prepair-update request   +        .thenReturn(loadResponseFromFile("/data/zmr/seq_1-8_search_with_personalId_only_resp.xml"))          +        //do not make an update because, MDS update is not allowed and no other data has been changed +        .thenThrow(new RuntimeException("This request is not needed any more"));                        + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8")); +          // execute test      task.execute(pendingReq, executionContext); @@ -201,13 +229,71 @@ public class InitialSearchTaskWithRegistersTest {          oldGivenName, "1994-12-31", DE);      // validate request -    assertEquals("wrong number of req.", 1, zmrReq.getAllValues().size()); +    assertEquals("wrong number of req.", 2, zmrReq.getAllValues().size());      assertNotNull("Personensuche req.", zmrReq.getValue().getPersonSuchenRequest()); -    checkBasicRequestParameters(zmrReq.getValue(), ZmrClientTest.PROCESS_TASK_SEARCH, null, "jUnit123456"); +    checkBasicRequestParameters(zmrReq.getValue(), ZmrClientTest.PROCESS_TASK_SEARCH,  +        new BigInteger("367100000000079"), "jUnit123456");    } +  /** +   * One match, but register update needed +   * <p> +   * <b>Check if ZMR update request is executed in case of other data than MDS change!</b> +   * </p> +   */ +  @Test +  @DirtiesContext +  public void singlePersonalIdMatchUpdateNecessary_ZmrDone() throws Exception { + +    String oldGivenName = "XXXClaus - Maria"; +    String placeOfBirth = RandomStringUtils.randomAlphabetic(5); +     +    //inject eIDAS data +    pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( +        Constants.DATA_FULL_EIDAS_RESPONSE, +        buildDummyAuthResponse(oldGivenName, "XXXvon Brandenburg", +            "DE/AT/7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit", "1994-12-31", null, placeOfBirth, null)); + +    final ArgumentCaptor<RequestType> zmrReq = ArgumentCaptor.forClass(RequestType.class); + +    // inject response +    when(zmrMock.service(zmrReq.capture(), any())) +        .thenReturn(loadResponseFromFile("/data/zmr/seq_1-8_search_with_personalId_only_resp_no_additional_attributes.xml")) +         +        //perform prepair-update request   +        .thenReturn(loadResponseFromFile("/data/zmr/seq_1-8_search_with_personalId_only_resp_no_additional_attributes.xml"))          + +        //do make an update because, MDS DOES NOT change, but additional attribute was available +        .thenReturn(loadResponseFromFile("/data/zmr/seq_3-6_kitt_update_resp.xml"));     + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8")); + +    // execute test +    task.execute(pendingReq, executionContext); + +    // validate state +    //INFO: has to be the old givenName because ZMR allows no update of MDS information +    checkMatchingSuccessState(pendingReq, "UgeknNsc26lVuB7U/uYGVmWtnnA=", "XXXvon Brandenburg", +        oldGivenName, "1994-12-31", DE); + +    // validate request +    assertEquals("wrong number of req.", 3, zmrReq.getAllValues().size()); +    assertNotNull("Personensuche req.", zmrReq.getAllValues().get(0).getPersonSuchenRequest()); +    checkBasicRequestParameters(zmrReq.getAllValues().get(0), ZmrClientTest.PROCESS_TASK_SEARCH, null, "jUnit123456"); +    assertNotNull("Personenupdate req.", zmrReq.getAllValues().get(2).getPersonAendernRequest()); +    checkBasicRequestParameters(zmrReq.getAllValues().get(2), ZmrClientTest.PROCESS_TASK_UPDATE,  +        new BigInteger("367100000000079"), "jUnit123456"); +    assertEquals("eIDAS attribute to add", 4,  +       zmrReq.getAllValues().get(2).getPersonAendernRequest().getEidasIdentitaetAnlage().size());        +    assertNull("ZMR update MDS", zmrReq.getAllValues().get(2).getPersonAendernRequest().getPersonAenderung()); +         +  } +   +      /**     * Two matches by PersonalId found in ZMR     * @@ -239,6 +325,58 @@ public class InitialSearchTaskWithRegistersTest {    } +  /** +   * Find single person in ZMR by country specifics. +   */ +  @Test +  @DirtiesContext +  public void singlePersonFindWithCountySpecifics_Ernp() throws Exception { +    //inject eIDAS data +    pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession( +        Constants.DATA_FULL_EIDAS_RESPONSE, +        buildDummyAuthResponse("vdqZZIaA", "mRjMKAQc", +            "DE/AT/nj1m79jm9z", "1996-01-01", +            null, "VRNCAylF", "miEklFHC")); + +    final ArgumentCaptor<RequestType> zmrReq = ArgumentCaptor.forClass(RequestType.class); +    BigInteger processId = new BigInteger("367100000000079"); + +    // inject response +    when(zmrMock.service(zmrReq.capture(), any())) +        .thenReturn(loadResponseFromFile("/data/zmr/empty_zmr_result.xml"))   //personalId search +        .thenReturn(loadResponseFromFile("/data/zmr/empty_zmr_result.xml"))  //CC specific search +        .thenThrow(new RuntimeException("This request is not needed any more")); + +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //personalId search +        .setBody("{}")                                                     +        .setHeader("Content-Type", "application/json;charset=utf-8")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //CC specific search   +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/2_search_with_cc_specific_resp.json"), "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8"));     +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //KITT search   +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/2_kitt_search_latest_resp.json"), "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //KITT update   +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/2_kitt_update_resp.json"), "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +         +    // execute test +    task.execute(pendingReq, executionContext); + +    // validate state +    checkMatchingSuccessState(pendingReq, "TBGoMlirU881e2jMGETa9WLx1+A=", "mRjMKAQc", +        "vdqZZIaA", "1996-01-01", DE); + +    // validate request +    assertEquals("wrong number of req.", 2, zmrReq.getAllValues().size()); +    checkBasicRequestParameters(zmrReq.getAllValues().get(0), ZmrClientTest.PROCESS_TASK_SEARCH, null, "jUnit123456"); +    checkBasicRequestParameters(zmrReq.getAllValues().get(1), ZmrClientTest.PROCESS_TASK_SEARCH, processId, "jUnit123456"); + +  } +      /**     * Find single person in ZMR by country specifics. @@ -264,6 +402,15 @@ public class InitialSearchTaskWithRegistersTest {          .thenReturn(loadResponseFromFile("/data/zmr/seq_1-6_kitt_update_resp.xml"))  //KITT update          .thenThrow(new RuntimeException("This request is not needed any more")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //CC specific search   +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +          // execute test      task.execute(pendingReq, executionContext); @@ -302,7 +449,13 @@ public class InitialSearchTaskWithRegistersTest {          //CC-specific will be ignored because CC is DE but BirthName and PlaceOfBirth is 'null'          .thenReturn(loadResponseFromFile("/data/zmr/seq_1-2_search_with_mds_resp.xml"))  //MDS specific search          .thenThrow(new RuntimeException("This request is not needed any more")); - +     +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //MDS specific search +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8"));      // execute test      task.execute(pendingReq, executionContext); @@ -342,11 +495,23 @@ public class InitialSearchTaskWithRegistersTest {          .thenThrow(new RuntimeException("This request is not needed any more")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200) +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //CC specific search   +        .setBody("{}") +        .setHeader("Content-Type", "application/json;charset=utf-8")); +    mockWebServer.enqueue(new MockResponse().setResponseCode(200)         //MDS specific search +        .setBody(IOUtils.toString( +            ErnpRestClientTest.class.getResourceAsStream("/data/ernp/3_search_with_mds_resp.json"), "UTF-8")) +        .setHeader("Content-Type", "application/json;charset=utf-8")); +     +          // execute test      task.execute(pendingReq, executionContext);      // validate state -    checkIntermediateResult(2); +    checkIntermediateResult(3);      // validate request      assertEquals("wrong number of req.", 3, zmrReq.getAllValues().size()); diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskRegisterTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskRegisterTest.java new file mode 100644 index 00000000..4f1ff61b --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskRegisterTest.java @@ -0,0 +1,337 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.lang3.RandomStringUtils; +import org.jetbrains.annotations.NotNull; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.github.skjolber.mockito.soap.SoapServiceRule; +import com.google.common.collect.Lists; + +import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummyConfigMap; +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; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult; +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.service.RegisterSearchService; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService.RegisterOperationStatus; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService.RegisterStatusResults; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.test.clients.ZmrClientTest; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils; +import at.gv.bmi.namespace.zmr_su.base._20040201.ResponseType; +import at.gv.bmi.namespace.zmr_su.base._20040201_.ServicePort; +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.EaafStorageException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; +import lombok.SneakyThrows; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { +    "/SpringTest-context_tasks_test.xml", +    "/SpringTest-context_basic_mapConfig.xml" +}) +public class ReceiveAustrianResidenceGuiResponseTaskRegisterTest { + +  @Autowired +  protected MsConnectorDummyConfigMap authConfig; + +  @Autowired +  private RegisterSearchService registerSearchService; + +  @Rule +  public SoapServiceRule soap = SoapServiceRule.newInstance();     +  private ServicePort zmrMock = null; +  private static JAXBContext jaxbContext; +   +  private ReceiveAustrianResidenceGuiResponseTask task; +  private ExecutionContext executionContext; +  private MockHttpServletRequest httpReq; +  private MockHttpServletResponse httpResp; +  private TestRequestImpl pendingReq; +   + +  /** +   * Initialize jUnit class. +   */ +  @BeforeClass +  @SneakyThrows +  public static void classInitializer() { +    jaxbContext = JAXBContext.newInstance( +        at.gv.bmi.namespace.zmr_su.zmr._20040201.ObjectFactory.class, +        at.gv.bmi.namespace.zmr_su.gis._20070725.ObjectFactory.class, +        at.gv.bmi.namespace.zmr_su.base._20040201.ObjectFactory.class); +         +  } +   +  /** +   * jUnit test set-up. +   * +   * @throws Exception In case of an set-up error +   */ +  @Before +  public void setUp() throws Exception { +    if (zmrMock == null) { +      zmrMock = soap.mock(ServicePort.class, "http://localhost:1234/demozmr"); + +    } +     +    executionContext = new ExecutionContextImpl(); +    task = new ReceiveAustrianResidenceGuiResponseTask(registerSearchService); +     +    httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    httpResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + +    pendingReq = new TestRequestImpl(); +    pendingReq.setAuthUrl("https://localhost/ms_connector"); +    pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); + +    LocaleContextHolder.resetLocaleContext(); +  } + +  @Test +  public void canceledByUser() throws Exception { +    AdresssucheOutput userInput = setupUserInput(); +    SimpleEidasData eidasData = setupEidasData(); +    RegisterStatusResults registerSearchResult = buildEmptyResult(); +    MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); +    httpReq.setParameter(ReceiveAustrianResidenceGuiResponseTask.HTTP_PARAM_NO_RESIDENCE, "true"); +     +    task.execute(pendingReq, executionContext); + +    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.20", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON));     +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq)); +     +  } +   +  @Test +  public void noRegisterResult() throws Exception { +    setupUserInput(); +    setupEidasData(); +    RegisterStatusResults registerSearchResult = buildEmptyResult(); +    MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); + +    // inject ZMR response +    when(zmrMock.service(any(), any())) +        .thenReturn(loadResponseFromFile("/data/zmr/empty_zmr_result.xml")); +     +    // execute task +    task.execute(pendingReq, executionContext); +     +    // validate state +    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.22", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON)); +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq)); +     +  } + +  @Test +  public void exactlyOneRegisterResult_Update() throws Exception { +    setupUserInput(); +    SimpleEidasData eidasData = setupEidasData(); +    RegisterStatusResults registerSearchResult = buildResultWithOneMatch(buildMatchingRegisterResult(eidasData)); +    MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); + +    // inject ZMR response +    when(zmrMock.service(any(), any())) +        .thenReturn(loadResponseFromFile("/data/zmr/search_with_personalId_only_resp.xml")) +        .thenReturn(loadResponseFromFile("/data/zmr/seq_3-4_kitt_get_latest_version_resp.xml")) +        .thenReturn(loadResponseFromFile("/data/zmr/seq_3-6_kitt_update_resp.xml")); +     +    task.execute(pendingReq, executionContext); +         +    // validate state +    assertNull("Transition To S9", executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK)); +    MatchedPersonResult matchingResult = MatchingTaskUtils.getFinalMatchingResult(pendingReq); +    assertNotNull("no final matching result", matchingResult);   +     +  } + +  @Test +  public void exactlyOneRegisterResult_UpdateFailedByZmrError() throws Exception { +    setupUserInput(); +    SimpleEidasData eidasData = setupEidasData(); +    RegisterStatusResults registerSearchResult = buildResultWithOneMatch(buildMatchingRegisterResult(eidasData)); +    MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); + +    // inject ZMR response +    when(zmrMock.service(any(), any())) +        .thenReturn(loadResponseFromFile("/data/zmr/search_with_personalId_only_resp.xml"))         +        .thenReturn(loadResponseFromFile("/data/zmr/seq_3-4_kitt_get_latest_version_resp.xml")) +        .thenThrow(new RuntimeException("ZMR update should fail for that test")); +                 +    TaskExecutionException error = assertThrows("wrong exception", TaskExecutionException.class, +        () -> task.execute(pendingReq, executionContext)); + +    assertEquals("wrong errorId", "module.eidasauth.matching.04", ((EaafException) error.getOriginalException()).getErrorId());     +     +  } +   +  @Test +  public void zmrError() throws Exception { +    setupUserInput(); +    setupEidasData(); +    RegisterStatusResults registerSearchResult = buildResultWithTwoMatches(); +    MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); + +    TaskExecutionException error = assertThrows("wrong exception", TaskExecutionException.class, +        () -> task.execute(pendingReq, executionContext)); + +    assertEquals("wrong errorId", "module.eidasauth.matching.03", ((EaafException) error.getOriginalException()).getErrorId());     +     +  } + +  @SneakyThrows +  private void validateMatchedPerson(MatchedPersonResult current, +      RegisterStatusResults registerUpdateResult) {    +    RegisterResult expected = registerUpdateResult.getResult();     +    assertEquals("familyName", expected.getFamilyName(), current.getFamilyName()); +    assertEquals("givenName", expected.getGivenName(), current.getGivenName()); +    assertEquals("birthday", expected.getDateOfBirth(), current.getDateOfBirth()); +    assertEquals("bpk", expected.getBpk(), current.getBpk()); +     +  } +   +  @NotNull +  private RegisterStatusResults buildEmptyResult() { +    return new RegisterStatusResults(new RegisterOperationStatus(generateRandomProcessId()), +        Collections.emptyList(), Collections.emptyList()); + +  } + +  private BigInteger generateRandomProcessId() { +    return new BigInteger(RandomStringUtils.randomNumeric(10)); + +  } + +  @NotNull +  private RegisterStatusResults buildResultWithOneMatch(RegisterResult registerResult) { +    return new RegisterStatusResults(new RegisterOperationStatus(generateRandomProcessId()), +        Collections.singletonList(registerResult), Collections.emptyList()); + +  } + +  @NotNull +  private RegisterStatusResults buildResultWithTwoMatches() { +    List<RegisterResult> results = Lists.newArrayList(buildRandomRegisterResult(), buildRandomRegisterResult()); +    return new RegisterStatusResults(new RegisterOperationStatus(generateRandomProcessId()), +        results, Collections.emptyList()); + +  } + +  @NotNull +  private RegisterResult buildRandomRegisterResult() { +    return RegisterResult.builder() +            .pseudonym(Arrays.asList(RandomStringUtils.randomAlphabetic(8))) +            .givenName(RandomStringUtils.randomAlphabetic(8)) +            .familyName(RandomStringUtils.randomAlphabetic(8)) +            .dateOfBirth(RandomStringUtils.randomAlphabetic(8)) +            .bpk(RandomStringUtils.randomAlphabetic(8)) +            .build(); + +  } + +  private RegisterResult buildMatchingRegisterResult(SimpleEidasData eidData) { +    return RegisterResult.builder() +        .pseudonym(Arrays.asList(eidData.getPseudonym())) +        .givenName(eidData.getGivenName()) +        .familyName(eidData.getFamilyName()) +        .dateOfBirth(eidData.getDateOfBirth()) +        .bpk(RandomStringUtils.randomAlphabetic(8)) +        .build(); + +  } + +  private RegisterResult buildNotMatchingRegisterResult(SimpleEidasData eidData) { +    return RegisterResult.builder() +        .pseudonym(Arrays.asList(eidData.getPseudonym() + RandomStringUtils.randomAlphabetic(8))) +        .givenName(eidData.getGivenName()) +        .familyName(eidData.getFamilyName()) +        .dateOfBirth(eidData.getDateOfBirth()) +        .bpk(RandomStringUtils.randomAlphabetic(8)) +        .build(); + +  } + +  private void setHttpParameters(AdresssucheOutput input) { +    httpReq.setParameter(AdresssucheController.PARAM_STREET, input.getStreet()); +    httpReq.setParameter(AdresssucheController.PARAM_MUNIPICALITY, input.getMunicipality()); +    httpReq.setParameter(AdresssucheController.PARAM_NUMBER, input.getNumber()); +    httpReq.setParameter(AdresssucheController.PARAM_VILLAGE, input.getVillage()); +    httpReq.setParameter(AdresssucheController.PARAM_POSTLEITZAHL, input.getPostleitzahl()); +     +  } + +  @NotNull +  private SimpleEidasData setupEidasData() throws EaafStorageException { +    SimpleEidasData result = SimpleEidasData.builder() +        .pseudonym(RandomStringUtils.randomAlphabetic(8)) +        .familyName(RandomStringUtils.randomAlphabetic(8)) +        .givenName(RandomStringUtils.randomAlphabetic(8)) +        .dateOfBirth("1970-01-01") +        .build(); +    AuthProcessDataWrapper authProcessDataWrapper = pendingReq.getSessionData(AuthProcessDataWrapper.class); +    authProcessDataWrapper.setGenericDataToSession(Constants.DATA_SIMPLE_EIDAS, result); +    return result; +  } + +  @NotNull +  private AdresssucheOutput setupUserInput() { +    AdresssucheOutput result = new AdresssucheOutput( +        RandomStringUtils.randomAlphabetic(8),  +        RandomStringUtils.randomAlphabetic(8),  +        RandomStringUtils.randomAlphabetic(8), +        RandomStringUtils.randomAlphabetic(8), +        RandomStringUtils.randomAlphabetic(8)); +    setHttpParameters(result); +    return result; +  } + +  private ResponseType loadResponseFromFile(String filepath) throws JAXBException { +    final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); +    JAXBElement<?> resp = (JAXBElement<?>) unmarshaller.unmarshal(ZmrClientTest.class.getResourceAsStream( +        filepath)); +    return (ResponseType) resp.getValue(); + +  } +   +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java index 64bb0d48..7758e021 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveAustrianResidenceGuiResponseTaskTest.java @@ -1,14 +1,9 @@  package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks; -import static at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask.PARAM_CITY; -import static at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask.PARAM_FORMER_RESIDENCE_AVAILABLE; -import static at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask.PARAM_STREET; -import static at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask.PARAM_ZIPCODE;  import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull;  import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows;  import static org.mockito.ArgumentMatchers.eq; -import static org.springframework.util.Assert.isInstanceOf;  import java.math.BigInteger;  import java.util.Arrays; @@ -21,7 +16,6 @@ import org.junit.Before;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.mockito.Mockito; -import org.mockito.MockitoAnnotations;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.test.mock.mockito.MockBean;  import org.springframework.context.i18n.LocaleContextHolder; @@ -36,21 +30,22 @@ import com.google.common.collect.Lists;  import at.asitplus.eidas.specific.connector.test.config.dummy.MsConnectorDummyConfigMap;  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; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;  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.exception.ManualFixNecessaryException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService.RegisterOperationStatus;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService.RegisterStatusResults;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.ReceiveAustrianResidenceGuiResponseTask.UserInput;  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.EaafStorageException; -import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;  import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;  import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;  import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; +import lombok.SneakyThrows;  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration(locations = { @@ -67,7 +62,7 @@ public class ReceiveAustrianResidenceGuiResponseTaskTest {    private ReceiveAustrianResidenceGuiResponseTask task; -  private final ExecutionContext executionContext = new ExecutionContextImpl(); +  private ExecutionContext executionContext;    private MockHttpServletRequest httpReq;    private MockHttpServletResponse httpResp;    private TestRequestImpl pendingReq; @@ -79,8 +74,9 @@ public class ReceiveAustrianResidenceGuiResponseTaskTest {     */    @Before    public void setUp() throws Exception { +    executionContext = new ExecutionContextImpl();      task = new ReceiveAustrianResidenceGuiResponseTask(registerSearchService); - +          httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector");      httpResp = new MockHttpServletResponse();      RequestContextHolder.resetRequestAttributes(); @@ -94,8 +90,40 @@ public class ReceiveAustrianResidenceGuiResponseTaskTest {    }    @Test +  public void canceledByUser() throws Exception { +    AdresssucheOutput userInput = setupUserInput(); +    SimpleEidasData eidasData = setupEidasData(); +    RegisterStatusResults registerSearchResult = buildEmptyResult(); +    mockRegisterSearch(userInput, registerSearchResult, eidasData); +    MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); +    httpReq.setParameter(ReceiveAustrianResidenceGuiResponseTask.HTTP_PARAM_NO_RESIDENCE, "true"); +     +    task.execute(pendingReq, executionContext); + +    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.20", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON));     +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq)); +     +  } +   +  @Test +  public void noInputData() throws Exception { +    RegisterStatusResults registerSearchResult = buildEmptyResult(); +    MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); + +    task.execute(pendingReq, executionContext); + +    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.21", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON)); +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq)); +     +  } +   +  @Test    public void noRegisterResult() throws Exception { -    UserInput userInput = setupUserInput(); +    AdresssucheOutput userInput = setupUserInput();      SimpleEidasData eidasData = setupEidasData();      RegisterStatusResults registerSearchResult = buildEmptyResult();      mockRegisterSearch(userInput, registerSearchResult, eidasData); @@ -103,56 +131,86 @@ public class ReceiveAustrianResidenceGuiResponseTaskTest {      task.execute(pendingReq, executionContext); -    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK)); +    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.22", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON)); +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq)); +        }    @Test -  public void exactlyOneRegisterResult_Matching() throws Exception { -    UserInput userInput = setupUserInput(); +  public void exactlyOneRegisterResult_NoUpdate() throws Exception { +    AdresssucheOutput userInput = setupUserInput();      SimpleEidasData eidasData = setupEidasData();      RegisterStatusResults registerSearchResult = buildResultWithOneMatch(buildMatchingRegisterResult(eidasData));      MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult);      mockRegisterSearch(userInput, registerSearchResult, eidasData);      task.execute(pendingReq, executionContext); - +         +    // validate state      assertNull("Transition To S9", executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK)); -    Mockito.verify(registerSearchService).step7aKittProcess(eq(registerSearchResult), eq(eidasData)); - +    MatchedPersonResult matchingResult = MatchingTaskUtils.getFinalMatchingResult(pendingReq); +    assertNotNull("no final matching result", matchingResult); +    validateMatchedPerson(matchingResult, registerSearchResult);   +        }    @Test -  public void exactlyOneRegisterResult_NotMatching() throws Exception { -    UserInput userInput = setupUserInput(); +  public void exactlyOneRegisterResult_UpdateRequired() throws Exception { +    AdresssucheOutput userInput = setupUserInput();      SimpleEidasData eidasData = setupEidasData();      RegisterStatusResults registerSearchResult = buildResultWithOneMatch(buildNotMatchingRegisterResult(eidasData)); +    RegisterStatusResults registerUpdateResult = buildResultWithOneMatch(buildRandomRegisterResult());      MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult);      mockRegisterSearch(userInput, registerSearchResult, eidasData); - +    Mockito.when(registerSearchService.step7aKittProcess(eq(registerSearchResult), eq(eidasData))) +        .thenReturn(registerUpdateResult); +         +    // perform test      task.execute(pendingReq, executionContext); -    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK)); +    // validate state +    assertNull("Transition To S9", executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK)); +             +    MatchedPersonResult matchingResult = MatchingTaskUtils.getFinalMatchingResult(pendingReq); +    assertNotNull("no final matching result", matchingResult); +    validateMatchedPerson(matchingResult, registerUpdateResult);        +        }    @Test    public void moreThanOneRegisterResult() throws Exception { -    UserInput userInput = setupUserInput(); +    AdresssucheOutput userInput = setupUserInput();      SimpleEidasData eidasData = setupEidasData();      RegisterStatusResults registerSearchResult = buildResultWithTwoMatches();      MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult);      mockRegisterSearch(userInput, registerSearchResult, eidasData); -    TaskExecutionException e = assertThrows(TaskExecutionException.class, -        () -> task.execute(pendingReq, executionContext)); +    task.execute(pendingReq, executionContext); -    assertEquals(pendingReq.getPendingRequestId(), e.getPendingRequestID()); -    isInstanceOf(ManualFixNecessaryException.class, e.getOriginalException()); -    assertNull("Transition To S16", executionContext.get(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK)); +    assertEquals("Transition To S9", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.22", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON)); +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq)); +        } -  private void mockRegisterSearch(UserInput userInput, RegisterStatusResults registerSearchResult, SimpleEidasData eidasData ) { +  @SneakyThrows +  private void validateMatchedPerson(MatchedPersonResult current, +      RegisterStatusResults registerUpdateResult) {    +    RegisterResult expected = registerUpdateResult.getResult();     +    assertEquals("familyName", expected.getFamilyName(), current.getFamilyName()); +    assertEquals("givenName", expected.getGivenName(), current.getGivenName()); +    assertEquals("birthday", expected.getDateOfBirth(), current.getDateOfBirth()); +    assertEquals("bpk", expected.getBpk(), current.getBpk()); +     +  } +   +  @SneakyThrows +  private void mockRegisterSearch(AdresssucheOutput userInput, RegisterStatusResults registerSearchResult, SimpleEidasData eidasData ) {      Mockito.when(registerSearchService.searchWithResidence(eq(registerSearchResult.getOperationStatus()), eq(eidasData), -        eq(userInput.getZipcode()), eq(userInput.getCity()), eq(userInput.getStreet()))).thenReturn(registerSearchResult); +        eq(userInput))).thenReturn(registerSearchResult);    }    @NotNull @@ -216,11 +274,13 @@ public class ReceiveAustrianResidenceGuiResponseTaskTest {    } -  private void setHttpParameters(UserInput input) { -    httpReq.setParameter(PARAM_FORMER_RESIDENCE_AVAILABLE, String.valueOf(input.isFormerResidenceAvailable())); -    httpReq.setParameter(PARAM_STREET, input.getStreet()); -    httpReq.setParameter(PARAM_CITY, input.getCity()); -    httpReq.setParameter(PARAM_ZIPCODE, input.getZipcode()); +  private void setHttpParameters(AdresssucheOutput input) { +    httpReq.setParameter(AdresssucheController.PARAM_STREET, input.getStreet()); +    httpReq.setParameter(AdresssucheController.PARAM_MUNIPICALITY, input.getMunicipality()); +    httpReq.setParameter(AdresssucheController.PARAM_NUMBER, input.getNumber()); +    httpReq.setParameter(AdresssucheController.PARAM_VILLAGE, input.getVillage()); +    httpReq.setParameter(AdresssucheController.PARAM_POSTLEITZAHL, input.getPostleitzahl()); +        }    @NotNull @@ -237,8 +297,13 @@ public class ReceiveAustrianResidenceGuiResponseTaskTest {    }    @NotNull -  private UserInput setupUserInput() { -    UserInput result = new UserInput(true, RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8), RandomStringUtils.randomAlphabetic(8)); +  private AdresssucheOutput setupUserInput() { +    AdresssucheOutput result = new AdresssucheOutput( +        RandomStringUtils.randomAlphabetic(8),  +        RandomStringUtils.randomAlphabetic(8),  +        RandomStringUtils.randomAlphabetic(8), +        RandomStringUtils.randomAlphabetic(8), +        RandomStringUtils.randomAlphabetic(8));      setHttpParameters(result);      return result;    } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveMobilePhoneSignatureResponseTaskTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveMobilePhoneSignatureResponseTaskTest.java index d5400695..b9133392 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveMobilePhoneSignatureResponseTaskTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/ReceiveMobilePhoneSignatureResponseTaskTest.java @@ -282,7 +282,10 @@ public class ReceiveMobilePhoneSignatureResponseTaskTest {      task.execute(pendingReq, executionContext); -    assertEquals("Transition To S16", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK)); +    assertEquals("Transition To S16", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.23", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON));     +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq));    } @@ -326,7 +329,10 @@ public class ReceiveMobilePhoneSignatureResponseTaskTest {      task.execute(pendingReq, executionContext);      assertEquals("Next task", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK)); -    assertEquals("advancedMatchingError flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("matching failed flag", true, executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); +    assertEquals("failed reason", "module.eidasauth.matching.24", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON));     +    assertNull("no final matching result", MatchingTaskUtils.getFinalMatchingResult(pendingReq)); +    }    //TODO: implement new test that this test makes no sense any more diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties index be716e95..d84777f3 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties @@ -8,9 +8,9 @@ eidas.ms.context.use.clustermode=true  eidas.ms.monitoring.eIDASNode.metadata.url= -eidas.ms.client.http.connection.timeout.socket=1 -eidas.ms.client.http.connection.timeout.connection=1 -eidas.ms.client.http.connection.timeout.request=1 +eidas.ms.client.http.connection.timeout.socket=5 +eidas.ms.client.http.connection.timeout.connection=5 +eidas.ms.client.http.connection.timeout.request=5  ##Specific logger configuration @@ -100,6 +100,19 @@ eidas.ms.auth.eIDAS.zmrclient.req.organisation.behoerdennr=jUnit123456  eidas.ms.auth.eIDAS.zmrclient.req.update.reason.code=EIDAS-KITT + +# ERnP communication +eidas.ms.auth.eIDAS.ernpclient.endpoint=http://localhost:1718/demoernp +eidas.ms.auth.eIDAS.ernpclient.req.organisation.behoerdennr=jUnit123456 +eidas.ms.auth.eIDAS.client.common.ssl.keyStore.type=jks +eidas.ms.auth.eIDAS.client.common.ssl.keyStore.path=../keystore/junit_test.jks +eidas.ms.auth.eIDAS.client.common.ssl.keyStore.password=password +eidas.ms.auth.eIDAS.client.common.ssl.key.alias=meta +eidas.ms.auth.eIDAS.client.common.ssl.key.password=password + + + +#### SP End-Points #####  ## PVP2 S-Profile end-point configuration  eidas.ms.pvp2.keystore.path=keys/.....  eidas.ms.pvp2.keystore.password= diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1_springboot.properties b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1_springboot.properties index 224e1b1f..0cc89a4a 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1_springboot.properties +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1_springboot.properties @@ -57,7 +57,18 @@ eidas.ms.auth.eIDAS.zmrclient.req.organisation.behoerdennr=jUnit123456  eidas.ms.auth.eIDAS.zmrclient.req.update.reason.code=EIDAS-KITT  eidas.ms.auth.eIDAS.zmrclient.req.update.reason.text=KITT for eIDAS Matching +# ERnP communication +eidas.ms.auth.eIDAS.ernpclient.endpoint=http://localhost:1718/demoernp +eidas.ms.auth.eIDAS.ernpclient.req.organisation.behoerdennr=jUnit123456 +eidas.ms.auth.eIDAS.client.common.ssl.keyStore.type=jks +eidas.ms.auth.eIDAS.client.common.ssl.keyStore.path=../keystore/junit_test.jks +eidas.ms.auth.eIDAS.client.common.ssl.keyStore.password=password +eidas.ms.auth.eIDAS.client.common.ssl.key.alias=meta +eidas.ms.auth.eIDAS.client.common.ssl.key.password=password + + +#### SP End-Points #####  ## PVP2 S-Profile end-point configuration  eidas.ms.pvp2.keystore.type=jks  eidas.ms.pvp2.keystore.path=keys/junit.jks diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_add_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_add_req.json new file mode 100644 index 00000000..4f823c60 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_add_req.json @@ -0,0 +1,30 @@ +{ +  "begruendung": "Add new person", +  "personendaten": { +    "familienname": "CtKKrtUe", +    "vorname": "dUeYzUFg", +    "geburtsdatum": { +      "jahr": 1985, +      "monat": 5, +      "tag": 5 +    } +  }, +  "anschrift": null, +  "eidas": [ +    { +      "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +      "wert": "Y8ADWaeh0h", +      "staatscode2": "DE" +    }, +    { +      "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +      "wert": "hrFevCfP", +      "staatscode2": "DE" +    }, +    { +      "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +      "wert": "sNUEAhEr", +      "staatscode2": "DE" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_add_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_add_resp.json new file mode 100644 index 00000000..139483cf --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_add_resp.json @@ -0,0 +1,60 @@ +{ +  "person": { +    "type": "Person", +    "eidas": [ +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000486", +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "staatscode2": "DE", +        "wert": "Y8ADWaeh0h" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000488", +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "staatscode2": "DE", +        "wert": "hrFevCfP" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000490", +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "staatscode2": "DE", +        "wert": "sNUEAhEr" +      } +    ], +    "entityId": "1933000000000475", +    "gueltigAb": "2022-03-03T11:07:28.885+01:00", +    "letzteOperation": { +      "begruendung": "Add new person", +      "durchgefuehrtVon": { +        "behoerdenkennzeichen": "380630", +        "benutzer": "eidtapp@bmi.gv.at" +      }, +      "vorgang": "PersonAnlegen", +      "zeitpunkt": "2022-03-03T11:07:28.885+01:00" +    }, +    "personendaten": { +      "basiszahl": "000482591530", +      "bpkZp": "+OQnljn0Son1W2rkM73nP/VMsvc=", +      "entityId": "1933000000000475", +      "familienname": "CtKKrtUe", +      "geburtsdatum": { +        "jahr": 1985, +        "monat": 5, +        "tag": 5 +      }, +      "geprueft": false, +      "gueltigAb": "2022-03-03T11:07:28.885+01:00", +      "vorname": "dUeYzUFg" +    }, +    "version": "2022-03-03T11:07:28.885+01:00" +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_search_latest_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_search_latest_req.json new file mode 100644 index 00000000..2538ebac --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_search_latest_req.json @@ -0,0 +1,19 @@ +{ +  "begruendung": "KITT get-latest-version", +  "suchoptionen": { +    "historisch": "AktuellUndHistorisch", +    "sucheMitNamensteilen": false, +    "suchwizard": false, +    "zmr": false +  }, +  "suchdaten": { +    "bpkZp": "+OQnljn0Son1W2rkM73nP/VMsvc=", +    "familienname": "CtKKrtUe", +    "vorname": "dUeYzUFg", +    "geburtsdatum": { +      "jahr": 1985, +      "monat": 5, +      "tag": 5 +    } +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_search_latest_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_search_latest_resp.json new file mode 100644 index 00000000..588153cd --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_search_latest_resp.json @@ -0,0 +1,62 @@ +{ +  "person": [ +    { +      "type": "Person", +      "eidas": [ +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000486", +          "gueltigAb": "2022-03-03T11:07:28.885+01:00", +          "staatscode2": "DE", +          "wert": "Y8ADWaeh0h" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000488", +          "gueltigAb": "2022-03-03T11:07:28.885+01:00", +          "staatscode2": "DE", +          "wert": "hrFevCfP" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000490", +          "gueltigAb": "2022-03-03T11:07:28.885+01:00", +          "staatscode2": "DE", +          "wert": "sNUEAhEr" +        } +      ], +      "entityId": "1933000000000475", +      "gueltigAb": "2022-03-03T11:07:28.885+01:00", +      "letzteOperation": { +        "begruendung": "Add new person", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "380630", +          "benutzer": "eidtapp@bmi.gv.at" +        }, +        "vorgang": "PersonAnlegen", +        "zeitpunkt": "2022-03-03T11:07:28.885+01:00" +      }, +      "personendaten": { +        "basiszahl": "000482591530", +        "bpkZp": "+OQnljn0Son1W2rkM73nP/VMsvc=", +        "entityId": "1933000000000475", +        "familienname": "CtKKrtUe", +        "geburtsdatum": { +          "jahr": 1985, +          "monat": 5, +          "tag": 5 +        }, +        "geprueft": false, +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "vorname": "dUeYzUFg" +      }, +      "version": "2022-03-03T11:07:28.885+01:00" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_update_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_update_req.json new file mode 100644 index 00000000..194fba1d --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_update_req.json @@ -0,0 +1,17 @@ +{ +  "begruendung": "KITT update dataset", +  "aendern": { +    "personendaten": { +      "entityId": "1933000000000475", +      "familienname": "mVzTMpig6r", +      "vorname": "Jb2vj1Xpql", +      "geburtsdatum": { +        "jahr": 1985, +        "monat": 5, +        "tag": 5 +      } +    } +  }, +  "entityId": "1933000000000475", +  "version": "2022-03-03T10:07:28.885Z" +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_update_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_update_resp.json new file mode 100644 index 00000000..7fe9210a --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_kitt_update_resp.json @@ -0,0 +1,60 @@ +{ +  "person": { +    "type": "Person", +    "eidas": [ +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000486", +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "staatscode2": "DE", +        "wert": "Y8ADWaeh0h" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000488", +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "staatscode2": "DE", +        "wert": "hrFevCfP" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000490", +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "staatscode2": "DE", +        "wert": "sNUEAhEr" +      } +    ], +    "entityId": "1933000000000475", +    "gueltigAb": "2022-03-03T11:07:29.751+01:00", +    "letzteOperation": { +      "begruendung": "KITT update dataset", +      "durchgefuehrtVon": { +        "behoerdenkennzeichen": "380630", +        "benutzer": "eidtapp@bmi.gv.at" +      }, +      "vorgang": "PersonAendern", +      "zeitpunkt": "2022-03-03T11:07:29.751+01:00" +    }, +    "personendaten": { +      "basiszahl": "000482591530", +      "bpkZp": "+OQnljn0Son1W2rkM73nP/VMsvc=", +      "entityId": "1933000000000475", +      "familienname": "mVzTMpig6r", +      "geburtsdatum": { +        "jahr": 1985, +        "monat": 5, +        "tag": 5 +      }, +      "geprueft": false, +      "gueltigAb": "2022-03-03T11:07:29.751+01:00", +      "vorname": "Jb2vj1Xpql" +    }, +    "version": "2022-03-03T11:07:29.751+01:00" +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_search_with_personalId_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_search_with_personalId_req.json new file mode 100644 index 00000000..d7344f08 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_search_with_personalId_req.json @@ -0,0 +1,20 @@ +{ +  "begruendung": "Searching PersonIdentifier", +  "suchoptionen": { +    "historisch": "AktuellUndHistorisch", +    "sucheMitNamensteilen": false, +    "suchwizard": false, +    "zmr": false +  }, +  "suchdaten": { +    "familienname": null, +    "vorname": null, +    "eidas": [ +      { +        "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +        "wert": "Y8ADWaeh0h", +        "staatscode2": "DE" +      } +    ] +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_search_with_personalId_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_search_with_personalId_resp.json new file mode 100644 index 00000000..588153cd --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/1_search_with_personalId_resp.json @@ -0,0 +1,62 @@ +{ +  "person": [ +    { +      "type": "Person", +      "eidas": [ +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000486", +          "gueltigAb": "2022-03-03T11:07:28.885+01:00", +          "staatscode2": "DE", +          "wert": "Y8ADWaeh0h" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000488", +          "gueltigAb": "2022-03-03T11:07:28.885+01:00", +          "staatscode2": "DE", +          "wert": "hrFevCfP" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000490", +          "gueltigAb": "2022-03-03T11:07:28.885+01:00", +          "staatscode2": "DE", +          "wert": "sNUEAhEr" +        } +      ], +      "entityId": "1933000000000475", +      "gueltigAb": "2022-03-03T11:07:28.885+01:00", +      "letzteOperation": { +        "begruendung": "Add new person", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "380630", +          "benutzer": "eidtapp@bmi.gv.at" +        }, +        "vorgang": "PersonAnlegen", +        "zeitpunkt": "2022-03-03T11:07:28.885+01:00" +      }, +      "personendaten": { +        "basiszahl": "000482591530", +        "bpkZp": "+OQnljn0Son1W2rkM73nP/VMsvc=", +        "entityId": "1933000000000475", +        "familienname": "CtKKrtUe", +        "geburtsdatum": { +          "jahr": 1985, +          "monat": 5, +          "tag": 5 +        }, +        "geprueft": false, +        "gueltigAb": "2022-03-03T11:07:28.885+01:00", +        "vorname": "dUeYzUFg" +      }, +      "version": "2022-03-03T11:07:28.885+01:00" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_add_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_add_req.json new file mode 100644 index 00000000..35e52c10 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_add_req.json @@ -0,0 +1,30 @@ +{ +  "begruendung": "Add new person", +  "personendaten": { +    "familienname": "mRjMKAQc", +    "vorname": "vdqZZIaA", +    "geburtsdatum": { +      "jahr": 1996, +      "monat": 1, +      "tag": 1 +    } +  }, +  "anschrift": null, +  "eidas": [ +    { +      "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +      "wert": "88hvWzUaIX", +      "staatscode2": "DE" +    }, +    { +      "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +      "wert": "VRNCAylF", +      "staatscode2": "DE" +    }, +    { +      "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +      "wert": "miEklFHC", +      "staatscode2": "DE" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_add_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_add_resp.json new file mode 100644 index 00000000..7f85a143 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_add_resp.json @@ -0,0 +1,60 @@ +{ +  "person": { +    "type": "Person", +    "eidas": [ +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000509", +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "staatscode2": "DE", +        "wert": "88hvWzUaIX" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000511", +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "staatscode2": "DE", +        "wert": "VRNCAylF" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000513", +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "staatscode2": "DE", +        "wert": "miEklFHC" +      } +    ], +    "entityId": "1933000000000498", +    "gueltigAb": "2022-03-03T11:14:59.712+01:00", +    "letzteOperation": { +      "begruendung": "Add new person", +      "durchgefuehrtVon": { +        "behoerdenkennzeichen": "380630", +        "benutzer": "eidtapp@bmi.gv.at" +      }, +      "vorgang": "PersonAnlegen", +      "zeitpunkt": "2022-03-03T11:14:59.712+01:00" +    }, +    "personendaten": { +      "basiszahl": "000951265372", +      "bpkZp": "TBGoMlirU881e2jMGETa9WLx1+A=", +      "entityId": "1933000000000498", +      "familienname": "mRjMKAQc", +      "geburtsdatum": { +        "jahr": 1996, +        "monat": 1, +        "tag": 1 +      }, +      "geprueft": false, +      "gueltigAb": "2022-03-03T11:14:59.712+01:00", +      "vorname": "vdqZZIaA" +    }, +    "version": "2022-03-03T11:14:59.712+01:00" +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_search_latest_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_search_latest_req.json new file mode 100644 index 00000000..d3dd0658 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_search_latest_req.json @@ -0,0 +1,19 @@ +{ +  "begruendung": "KITT get-latest-version", +  "suchoptionen": { +    "historisch": "AktuellUndHistorisch", +    "sucheMitNamensteilen": false, +    "suchwizard": false, +    "zmr": false +  }, +  "suchdaten": { +    "bpkZp": "TBGoMlirU881e2jMGETa9WLx1+A=", +    "familienname": "mRjMKAQc", +    "vorname": "vdqZZIaA", +    "geburtsdatum": { +      "jahr": 1996, +      "monat": 1, +      "tag": 1 +    } +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_search_latest_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_search_latest_resp.json new file mode 100644 index 00000000..24009e64 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_search_latest_resp.json @@ -0,0 +1,62 @@ +{ +  "person": [ +    { +      "type": "Person", +      "eidas": [ +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000509", +          "gueltigAb": "2022-03-03T11:14:59.712+01:00", +          "staatscode2": "DE", +          "wert": "88hvWzUaIX" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000511", +          "gueltigAb": "2022-03-03T11:14:59.712+01:00", +          "staatscode2": "DE", +          "wert": "VRNCAylF" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000513", +          "gueltigAb": "2022-03-03T11:14:59.712+01:00", +          "staatscode2": "DE", +          "wert": "miEklFHC" +        } +      ], +      "entityId": "1933000000000498", +      "gueltigAb": "2022-03-03T11:14:59.712+01:00", +      "letzteOperation": { +        "begruendung": "Add new person", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "380630", +          "benutzer": "eidtapp@bmi.gv.at" +        }, +        "vorgang": "PersonAnlegen", +        "zeitpunkt": "2022-03-03T11:14:59.712+01:00" +      }, +      "personendaten": { +        "basiszahl": "000951265372", +        "bpkZp": "TBGoMlirU881e2jMGETa9WLx1+A=", +        "entityId": "1933000000000498", +        "familienname": "mRjMKAQc", +        "geburtsdatum": { +          "jahr": 1996, +          "monat": 1, +          "tag": 1 +        }, +        "geprueft": false, +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "vorname": "vdqZZIaA" +      }, +      "version": "2022-03-03T11:14:59.712+01:00" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_update_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_update_req.json new file mode 100644 index 00000000..0e4a9b21 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_update_req.json @@ -0,0 +1,14 @@ +{ +  "begruendung": "KITT update dataset", +  "anlegen": { +    "eidas": [ +      { +        "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +        "wert": "nj1m79jm9z", +        "staatscode2": "DE" +      } +    ] +  }, +  "entityId": "1933000000000498", +  "version": "2022-03-03T10:14:59.712Z" +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_update_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_update_resp.json new file mode 100644 index 00000000..23dc74f3 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_kitt_update_resp.json @@ -0,0 +1,69 @@ +{ +  "person": { +    "type": "Person", +    "eidas": [ +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000509", +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "staatscode2": "DE", +        "wert": "88hvWzUaIX" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000511", +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "staatscode2": "DE", +        "wert": "VRNCAylF" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933000000000513", +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "staatscode2": "DE", +        "wert": "miEklFHC" +      }, +      { +        "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +        "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +        "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +        "entityId": "1933100000000607", +        "gueltigAb": "2022-03-03T11:15:00.762+01:00", +        "staatscode2": "DE", +        "wert": "nj1m79jm9z" +      } +    ], +    "entityId": "1933000000000498", +    "gueltigAb": "2022-03-03T11:15:00.762+01:00", +    "letzteOperation": { +      "begruendung": "KITT update dataset", +      "durchgefuehrtVon": { +        "behoerdenkennzeichen": "380630", +        "benutzer": "eidtapp@bmi.gv.at" +      }, +      "vorgang": "PersonAendern", +      "zeitpunkt": "2022-03-03T11:15:00.762+01:00" +    }, +    "personendaten": { +      "basiszahl": "000951265372", +      "bpkZp": "TBGoMlirU881e2jMGETa9WLx1+A=", +      "entityId": "1933000000000498", +      "familienname": "mRjMKAQc", +      "geburtsdatum": { +        "jahr": 1996, +        "monat": 1, +        "tag": 1 +      }, +      "geprueft": false, +      "gueltigAb": "2022-03-03T11:14:59.712+01:00", +      "vorname": "vdqZZIaA" +    }, +    "version": "2022-03-03T11:15:00.762+01:00" +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_search_with_cc_specific_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_search_with_cc_specific_req.json new file mode 100644 index 00000000..d80b0d2e --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_search_with_cc_specific_req.json @@ -0,0 +1,30 @@ +{ +  "begruendung": "Searching DE specific", +  "suchoptionen": { +    "historisch": "AktuellUndHistorisch", +    "sucheMitNamensteilen": false, +    "suchwizard": false, +    "zmr": false +  }, +  "suchdaten": { +    "familienname": "mRjMKAQc", +    "vorname": "vdqZZIaA", +    "geburtsdatum": { +      "jahr": 1996, +      "monat": 1, +      "tag": 1 +    }, +    "eidas": [ +      { +        "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +        "wert": "VRNCAylF", +        "staatscode2": "DE" +      }, +      { +        "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +        "wert": "miEklFHC", +        "staatscode2": "DE" +      } +    ] +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_search_with_cc_specific_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_search_with_cc_specific_resp.json new file mode 100644 index 00000000..24009e64 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/2_search_with_cc_specific_resp.json @@ -0,0 +1,62 @@ +{ +  "person": [ +    { +      "type": "Person", +      "eidas": [ +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000509", +          "gueltigAb": "2022-03-03T11:14:59.712+01:00", +          "staatscode2": "DE", +          "wert": "88hvWzUaIX" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000511", +          "gueltigAb": "2022-03-03T11:14:59.712+01:00", +          "staatscode2": "DE", +          "wert": "VRNCAylF" +        }, +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/BirthName", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000513", +          "gueltigAb": "2022-03-03T11:14:59.712+01:00", +          "staatscode2": "DE", +          "wert": "miEklFHC" +        } +      ], +      "entityId": "1933000000000498", +      "gueltigAb": "2022-03-03T11:14:59.712+01:00", +      "letzteOperation": { +        "begruendung": "Add new person", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "380630", +          "benutzer": "eidtapp@bmi.gv.at" +        }, +        "vorgang": "PersonAnlegen", +        "zeitpunkt": "2022-03-03T11:14:59.712+01:00" +      }, +      "personendaten": { +        "basiszahl": "000951265372", +        "bpkZp": "TBGoMlirU881e2jMGETa9WLx1+A=", +        "entityId": "1933000000000498", +        "familienname": "mRjMKAQc", +        "geburtsdatum": { +          "jahr": 1996, +          "monat": 1, +          "tag": 1 +        }, +        "geprueft": false, +        "gueltigAb": "2022-03-03T11:14:59.712+01:00", +        "vorname": "vdqZZIaA" +      }, +      "version": "2022-03-03T11:14:59.712+01:00" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/3_search_with_mds_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/3_search_with_mds_req.json new file mode 100644 index 00000000..eb382bc0 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/3_search_with_mds_req.json @@ -0,0 +1,18 @@ +{ +  "begruendung": "Searching with MDS only", +  "suchoptionen": { +    "historisch": "AktuellUndHistorisch", +    "sucheMitNamensteilen": false, +    "suchwizard": false, +    "zmr": false +  }, +  "suchdaten": { +    "familienname": "DOPISN[0xc3][0x8d]", +    "vorname": "DANA", +    "geburtsdatum": { +      "jahr": 1996, +      "monat": 1, +      "tag": 1 +    } +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/3_search_with_mds_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/3_search_with_mds_resp.json new file mode 100644 index 00000000..87be362d --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/3_search_with_mds_resp.json @@ -0,0 +1,44 @@ +{ +  "person": [ +    { +      "type": "Person", +      "eidas": [ +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000058", +          "gueltigAb": "2022-03-02T16:23:32.743+01:00", +          "staatscode2": "CZ", +          "wert": "7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit" +        } +      ], +      "entityId": "1933000000000047", +      "gueltigAb": "2022-03-02T16:23:32.743+01:00", +      "letzteOperation": { +        "begruendung": "Add new person", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "380630", +          "benutzer": "eidtapp@bmi.gv.at" +        }, +        "vorgang": "PersonAnlegen", +        "zeitpunkt": "2022-03-02T16:23:32.743+01:00" +      }, +      "personendaten": { +        "basiszahl": "000501189333", +        "bpkZp": "vypyCkyczK7i+cgPWlJasuJphIA=", +        "entityId": "1933000000000047", +        "familienname": "DOPISNÍ", +        "geburtsdatum": { +          "jahr": 1996, +          "monat": 1, +          "tag": 1 +        }, +        "geprueft": false, +        "gueltigAb": "2022-03-02T16:23:32.743+01:00", +        "vorname": "DANA" +      }, +      "version": "2022-03-02T16:23:32.743+01:00" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/4_search_with_mds_multi_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/4_search_with_mds_multi_resp.json new file mode 100644 index 00000000..87a23647 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/4_search_with_mds_multi_resp.json @@ -0,0 +1,84 @@ +{ +  "person": [ +    { +      "type": "Person", +      "eidas": [ +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933000000000653", +          "gueltigAb": "2022-03-03T11:27:57.651+01:00", +          "staatscode2": "XZ", +          "wert": "ybgLmbYGxU" +        } +      ], +      "entityId": "1933000000000642", +      "gueltigAb": "2022-03-03T11:27:57.651+01:00", +      "letzteOperation": { +        "begruendung": "Add new person", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "380630", +          "benutzer": "eidtapp@bmi.gv.at" +        }, +        "vorgang": "PersonAnlegen", +        "zeitpunkt": "2022-03-03T11:27:57.651+01:00" +      }, +      "personendaten": { +        "basiszahl": "000693812023", +        "bpkZp": "QJ/5YLEbOCfRhG5R0KKHNnmeMYo=", +        "entityId": "1933000000000642", +        "familienname": "HjecFKGu", +        "geburtsdatum": { +          "jahr": 1996, +          "monat": 1, +          "tag": 1 +        }, +        "geprueft": false, +        "gueltigAb": "2022-03-03T11:27:57.651+01:00", +        "vorname": "QwnAMXsJ" +      }, +      "version": "2022-03-03T11:27:57.651+01:00" +    }, +    { +      "type": "Person", +      "eidas": [ +        { +          "ablaufDatum": "9999-12-31T00:00:00.000+01:00", +          "art": "http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier", +          "ausstellDatum": "9999-12-31T00:00:00.000+01:00", +          "entityId": "1933100000000762", +          "gueltigAb": "2022-03-03T11:27:57.885+01:00", +          "staatscode2": "XZ", +          "wert": "rEhBYWgiSx" +        } +      ], +      "entityId": "1933100000000751", +      "gueltigAb": "2022-03-03T11:27:57.885+01:00", +      "letzteOperation": { +        "begruendung": "Add new person", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "380630", +          "benutzer": "eidtapp@bmi.gv.at" +        }, +        "vorgang": "PersonAnlegen", +        "zeitpunkt": "2022-03-03T11:27:57.885+01:00" +      }, +      "personendaten": { +        "basiszahl": "000803465934", +        "bpkZp": "ZaJ2Yvx0u/z8VqNyCJ8zKT8XQa0=", +        "entityId": "1933100000000751", +        "familienname": "HjecFKGu", +        "geburtsdatum": { +          "jahr": 1996, +          "monat": 1, +          "tag": 1 +        }, +        "geprueft": false, +        "gueltigAb": "2022-03-03T11:27:57.885+01:00", +        "vorname": "QwnAMXsJ" +      }, +      "version": "2022-03-03T11:27:57.885+01:00" +    } +  ] +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/4_search_with_mds_req.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/4_search_with_mds_req.json new file mode 100644 index 00000000..01c3c3f9 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/4_search_with_mds_req.json @@ -0,0 +1,18 @@ +{ +  "begruendung": "Searching with MDS only", +  "suchoptionen": { +    "historisch": "AktuellUndHistorisch", +    "sucheMitNamensteilen": false, +    "suchwizard": false, +    "zmr": false +  }, +  "suchdaten": { +    "familienname": "HjecFKGu", +    "vorname": "QwnAMXsJ", +    "geburtsdatum": { +      "jahr": 1996, +      "monat": 1, +      "tag": 1 +    } +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/ernp_empty_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/ernp_empty_resp.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/ernp_empty_resp.json @@ -0,0 +1 @@ +{} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/ernp_handbook_example.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/ernp_handbook_example.json new file mode 100644 index 00000000..f4485ff7 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/ernp_handbook_example.json @@ -0,0 +1,85 @@ +{ +  "person": [ +    { +      "type": "Person", +      "anschrift": { +        "type": "AnschriftInland", +        "adressstatus": "XXXXXXXXX", +        "codes": { +          "gemeindekennziffer": "09988", +          "strassenkennziffer": "T80001" +        }, +        "entityId": 33069800000171092, +        "gemeinde": "Testgemeinde", +        "gueltigAb": "2011-09-06T11:23:55.306+02:00", +        "hausnummer": "99", +        "postleitzahl": "0077", +        "postort": "Testpostort 77 mit maximalmögl. Längen", +        "staat": { +          "isoCode3": "AUT", +          "name": "Österreich" +        }, +        "strasse": "Testgasse" +      }, +      "entityId": 33069800000171080, +      "gueltigAb": "2011-09-06T11:23:55.306+02:00", +      "letzteOperation": { +        "begruendung": "Testperson", +        "durchgefuehrtVon": { +          "behoerdenkennzeichen": "346743", +          "benutzer": "xlechne@bmi.gv.at" +        }, +        "vorgang": "PERSON_ANLEGEN", +        "zeitpunkt": "2011-09-06T11:23:55.306+02:00" +      }, +      "personendaten": { +        "basiszahl": "000766083209", +        "bpkZp": "BC1ifQanMKaDQG0yLBPbQ9AHgb4=", +        "entityId": 33069800000171080, +        "familienname": "XXXSZR", +        "geburtsbundesland": "Wien", +        "geburtsdatum": { +          "jahr": 1985, +          "monat": 1, +          "tag": 1 +        }, +        "geburtsort": "Wien", +        "geburtsstaat": { +          "isoCode3": "AUT", +          "name": "Österreich" +        }, +        "geprueft": true, +        "geschlecht": "Männlich", +        "gueltigAb": "2011-09-06T11:23:55.306+02:00", +        "vorname": "XXXTest" +      }, +      "reisedokument": [ +        { +          "art": "Personalausweis", +          "ausgestelltVon": { +            "behoerde": "Wien", +            "datum": "1985-01-01T00:00:00.000+01:00", +            "staat": { +              "isoCode3": "AUT", +              "name": "Österreich" +            } +          }, +          "entityId": 33069800000171090, +          "gueltigAb": "2011-09-06T11:23:55.306+02:00", +          "nummer": "123456789" +        } +      ], +      "staatsangehoerigkeit": [ +        { +          "entityId": 33069800000171084, +          "gueltigAb": "2011-09-06T11:23:55.306+02:00", +          "staat": { +            "isoCode3": "AUT", +            "name": "Österreich" +          } +        } +      ], +      "version": "2011-09-06T11:23:55.306+02:00" +    } +  ] +}
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/error_resp.json b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/error_resp.json new file mode 100644 index 00000000..76e3e7ba --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/ernp/error_resp.json @@ -0,0 +1,12 @@ +{ +  "faultDetails": { +    "fault": [ +      { +        "key": "suchdaten", +        "message": "Mindestsuchkriterien sind: Vorname & Familienname & Geburtsdatum (statt Familienname kann auch Name vor Ehe angegeben werden) oder mindestens ein Eidas Attribut (Art & Wert & Staat)" +      } +    ], +    "faultNumber": 100 +  }, +  "message": "Validierungsfehler" +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_1-8_search_with_personalId_only_resp.xml b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_1-8_search_with_personalId_only_resp.xml index 3fd477ee..f21c3698 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_1-8_search_with_personalId_only_resp.xml +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_1-8_search_with_personalId_only_resp.xml @@ -182,7 +182,76 @@                    <zmr:EidasWert>7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit</zmr:EidasWert>                    <base:AusstellDatum>9999-12-31</base:AusstellDatum>                    <base:AblaufDatum>9999-12-31</base:AblaufDatum> -                </zmr:EidasIdentitaet> +                </zmr:EidasIdentitaet>                 +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000005</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>XXXvon Brandenburg</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet>                +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000005</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>XXXClaus - Maria</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet>                 +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000005</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/DateOfBirth</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>1994-12-31</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet>                                                                                </zmr:PersonErgebnis>              </zmr:Personendaten>              <zmr:Meldedaten> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_1-8_search_with_personalId_only_resp_no_additional_attributes.xml b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_1-8_search_with_personalId_only_resp_no_additional_attributes.xml new file mode 100644 index 00000000..6551cdd3 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_1-8_search_with_personalId_only_resp_no_additional_attributes.xml @@ -0,0 +1,221 @@ +<?xml version="1.0" encoding="UTF-8"?> +    <base:Response xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://reference.e-government.gv.at/namespace/persondata/de/20040201#" xmlns:base="http://bmi.gv.at/namespace/zmr-su/base/20040201#" xmlns:smi="http://bmi.gv.at/namespace/zmr-su/smi/20060901#" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:zmr="http://bmi.gv.at/namespace/zmr-su/zmr/20040201#" xmlns:ns10="http://bmi.gv.at/namespace/zmr-su/ernp/20050901#" xmlns:ns11="http://bmi.gv.at/namespace/zmr-su/gis/20070725#" xmlns:ns12="http://egov.gv.at/pvp1.xsd" xmlns:ns13="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:ns8="http://bmi.gv.at/namespace/zmr-su/lmr/20050401#" xmlns:ns9="http://www.w3.org/2000/09/xmldsig#"> +      <base:WorkflowInfoServer> +        <base:ProzessName>GP_EIDAS</base:ProzessName> +        <base:ProzessInstanzID>367100000000079</base:ProzessInstanzID> +        <base:SequenzID>0</base:SequenzID> +      </base:WorkflowInfoServer> +      <base:ServerInfo> +        <base:GeneriertVon>ZMR-Server Version: 5.9.0.0-SNAPSHOT</base:GeneriertVon> +        <base:GeneriertAm>2021-11-12T08:24:40.985</base:GeneriertAm> +        <base:ServerTransaktionNr>1877300000000139</base:ServerTransaktionNr> +      </base:ServerInfo> +      <zmr:PersonSuchenResponse> +        <zmr:PersonensucheAnfrage> +          <zmr:PersonensucheInfo> +            <base:Bezugsfeld>Searching PersonIdentifier</base:Bezugsfeld> +            <zmr:Suchkriterien> +              <base:InclusivHistorie>true</base:InclusivHistorie> +              <base:Formalisiert>false</base:Formalisiert> +            </zmr:Suchkriterien> +            <zmr:Ergebniskriterien> +              <base:InclusivHistorie>false</base:InclusivHistorie> +            </zmr:Ergebniskriterien> +            <base:AnzahlSaetze>10</base:AnzahlSaetze> +          </zmr:PersonensucheInfo> +          <NatuerlichePerson/> +        </zmr:PersonensucheAnfrage> +        <base:Message> +          <base:Number>5020</base:Number> +          <base:Text>Person gefunden.</base:Text> +        </base:Message> +        <zmr:Personensuchergebnis> +          <base:GefundeneSaetze>1</base:GefundeneSaetze> +          <zmr:GefundeneSaetzeERnP>0</zmr:GefundeneSaetzeERnP> +          <base:SaetzeVon>0</base:SaetzeVon> +          <base:SaetzeBis>1</base:SaetzeBis> +          <zmr:PersonErgebnisSatz> +            <zmr:Personendaten> +              <zmr:PersonErgebnis> +                <base:ErgebnissatzInfo> +                  <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                </base:ErgebnissatzInfo> +                <base:EntityErgebnisReferenz> +                  <base:Technisch> +                    <base:EntityID>44453600000000697</base:EntityID> +                    <base:LetzteAenderung>2020-02-05T13:07:06.311</base:LetzteAenderung> +                  </base:Technisch> +                  <base:Von>2020-02-05T13:07:06.311</base:Von> +                  <base:BeginnCode>SONSTIGES</base:BeginnCode> +                  <base:BeginnText>Sonstiges</base:BeginnText> +                  <base:BeginnFreitext>Testerperson</base:BeginnFreitext> +                  <base:DurchgefuehrtVon> +                    <base:Organisation> +                      <base:Behoerdenschluessel>109091</base:Behoerdenschluessel> +                    </base:Organisation> +                  </base:DurchgefuehrtVon> +                </base:EntityErgebnisReferenz> +                <base:ZMRZahl>000430320173</base:ZMRZahl> +                <zmr:NatuerlichePerson> +                  <Identification> +                    <Value>UgeknNsc26lVuB7U/uYGVmWtnnA=</Value> +                    <Type>urn:publicid:gv.at:cdid+ZP</Type> +                  </Identification> +                  <zmr:PersonenName> +                    <Vorname>XXXClaus - Maria</Vorname> +                    <Familienname>XXXvon Brandenburg</Familienname> +                  </zmr:PersonenName> +                  <Familienstand>unbekannt</Familienstand> +                  <Geschlecht>männlich</Geschlecht> +                  <Geburtsdatum>1994-12-31</Geburtsdatum> +                  <Geburtsort>Wien</Geburtsort> +                  <Geburtsbundesland>Wien</Geburtsbundesland> +                  <Geburtsstaat>Österreich</Geburtsstaat> +                  <zmr:Staatsangehoerigkeit> +                    <ISOCode3>AUT</ISOCode3> +                    <StaatsnameDE>Österreich</StaatsnameDE> +                    <base:EntityErgebnisReferenz> +                      <base:Technisch> +                        <base:EntityID>44453600000000727</base:EntityID> +                        <base:LetzteAenderung>2020-02-05T13:07:06.311</base:LetzteAenderung> +                      </base:Technisch> +                      <base:Von>2020-02-05T13:07:06.311</base:Von> +                      <base:BeginnCode>STAATSANGEH_ANLEGEN</base:BeginnCode> +                      <base:BeginnText>Staatsangehörigkeit anlegen</base:BeginnText> +                      <base:BeginnFreitext>Testerperson</base:BeginnFreitext> +                      <base:DurchgefuehrtVon> +                        <base:Organisation> +                          <base:Behoerdenschluessel>109091</base:Behoerdenschluessel> +                        </base:Organisation> +                      </base:DurchgefuehrtVon> +                    </base:EntityErgebnisReferenz> +                  </zmr:Staatsangehoerigkeit> +                </zmr:NatuerlichePerson> +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000001</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/BirthName</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>XXXvon Heuburg</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet> +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000005</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>7cEYWithDEElementsasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet> +              </zmr:PersonErgebnis> +            </zmr:Personendaten> +            <zmr:Meldedaten> +              <zmr:MeldungErgebnis> +                <base:ErgebnissatzInfo> +                  <base:LetzteAenderung>2020-02-05T13:07:06.311</base:LetzteAenderung> +                </base:ErgebnissatzInfo> +                <base:EntityErgebnisReferenz> +                  <base:Technisch> +                    <base:EntityID>44453500000005242</base:EntityID> +                    <base:LetzteAenderung>2020-02-05T13:07:06.311</base:LetzteAenderung> +                  </base:Technisch> +                  <base:Von>2020-02-05T13:07:06.311</base:Von> +                  <base:BeginnCode>WSANM</base:BeginnCode> +                  <base:BeginnText>Wohnsitz anmelden</base:BeginnText> +                  <base:DurchgefuehrtVon> +                    <base:Organisation> +                      <base:Behoerdenschluessel>109091</base:Behoerdenschluessel> +                    </base:Organisation> +                  </base:DurchgefuehrtVon> +                </base:EntityErgebnisReferenz> +                <zmr:Wohnsitz> +                  <zmr:PostAdresse> +                    <Postleitzahl>0088</Postleitzahl> +                    <Gemeinde>Testgemeinde</Gemeinde> +                    <Gemeindekennziffer>09988</Gemeindekennziffer> +                    <Ortschaft>Testort A</Ortschaft> +                    <zmr:Zustelladresse> +                      <Strassenname>Testgasse</Strassenname> +                      <Orientierungsnummer>1a-2b</Orientierungsnummer> +                      <Gebaeude>Stg. 3c-4d</Gebaeude> +                      <Nutzungseinheit>5</Nutzungseinheit> +                      <Wohnsitzqualitaet>H</Wohnsitzqualitaet> +                      <Abgabestelle>false</Abgabestelle> +                      <Nutzungseinheitlaufnummer>0001</Nutzungseinheitlaufnummer> +                      <zmr:AdressRegisterEintrag> +                        <Adresscode>T800001</Adresscode> +                        <Subcode>001</Subcode> +                        <Objektnummer>T800001</Objektnummer> +                      </zmr:AdressRegisterEintrag> +                    </zmr:Zustelladresse> +                  </zmr:PostAdresse> +                  <base:Adressstatus>HST111WWW</base:Adressstatus> +                  <base:Adressschluessel> +                    <base:OKZ>T8001</base:OKZ> +                    <base:SKZ>T80001</base:SKZ> +                    <base:ADRRefkey>T80000000001</base:ADRRefkey> +                    <base:GBRRefkey>T80000000002</base:GBRRefkey> +                  </base:Adressschluessel> +                  <base:HauptIdent>H</base:HauptIdent> +                  <base:Postleitzahlgebiet>Testpostort</base:Postleitzahlgebiet> +                </zmr:Wohnsitz> +                <base:GemeldetVon>2020-02-05T13:07:06.311</base:GemeldetVon> +                <base:PeriodeCode>WSANM</base:PeriodeCode> +                <base:PeriodeText>Wohnsitz anmelden</base:PeriodeText> +                <zmr:Auskunftssperre> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>44453500000005262</base:EntityID> +                      <base:LetzteAenderung>2020-02-05T13:07:06.311</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2020-02-05T13:07:06.311</base:Von> +                    <base:BeginnCode>AUSK_SPERRE_SETZ</base:BeginnCode> +                    <base:BeginnText>Auskunftssperre setzen</base:BeginnText> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>109091</base:Behoerdenschluessel> +                      </base:Organisation> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:SperreVon>2020-02-05T13:07:06.311</zmr:SperreVon> +                  <zmr:SperreBis>9999-12-31T23:59:59.000</zmr:SperreBis> +                  <zmr:SperrCode>ASMG</zmr:SperrCode> +                  <zmr:SperrText>Auskunftssperre nach § 18 / 2ff MeldeG</zmr:SperrText> +                  <zmr:SperrFreitext>automatische Auskunftssperre</zmr:SperrFreitext> +                </zmr:Auskunftssperre> +              </zmr:MeldungErgebnis> +            </zmr:Meldedaten> +          </zmr:PersonErgebnisSatz> +        </zmr:Personensuchergebnis> +      </zmr:PersonSuchenResponse> +    </base:Response> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_3-8_kitt_get_latest_version_resp.xml b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_3-8_kitt_get_latest_version_resp.xml index 447d2b55..656164f2 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_3-8_kitt_get_latest_version_resp.xml +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/data/zmr/seq_3-8_kitt_get_latest_version_resp.xml @@ -146,7 +146,76 @@                    <zmr:EidasWert>7cEYasdfsafsaf4CDVzNT4E7cjkU4VqForjUnit</zmr:EidasWert>                    <base:AusstellDatum>9999-12-31</base:AusstellDatum>                    <base:AblaufDatum>9999-12-31</base:AblaufDatum> -                </zmr:EidasIdentitaet>                   +                </zmr:EidasIdentitaet>      +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000005</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>XXXvon Brandenburg</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet>                +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000005</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>XXXClaus - Maria</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet>                 +                <zmr:EidasIdentitaet> +                  <base:EntityErgebnisReferenz> +                    <base:Technisch> +                      <base:EntityID>1879000000000005</base:EntityID> +                      <base:LetzteAenderung>2021-11-12T08:24:39.695</base:LetzteAenderung> +                    </base:Technisch> +                    <base:Von>2021-11-12T08:24:39.695</base:Von> +                    <base:BeginnCode>EIDAS_ANLEGEN</base:BeginnCode> +                    <base:BeginnFreitext>KITT for eIDAS Matching</base:BeginnFreitext> +                    <base:DurchgefuehrtVon> +                      <base:Organisation> +                        <base:Behoerdenschluessel>101179</base:Behoerdenschluessel> +                      </base:Organisation> +                      <base:Benutzer>eidtapp@bmi.gv.at</base:Benutzer> +                    </base:DurchgefuehrtVon> +                  </base:EntityErgebnisReferenz> +                  <zmr:EidasArt>http://eidas.europa.eu/attributes/naturalperson/DateOfBirth</zmr:EidasArt> +                  <zmr:Staatscode2>DE</zmr:Staatscode2> +                  <base:AusstellBehoerde/> +                  <zmr:EidasWert>1994-12-31</zmr:EidasWert> +                  <base:AusstellDatum>9999-12-31</base:AusstellDatum> +                  <base:AblaufDatum>9999-12-31</base:AblaufDatum> +                </zmr:EidasIdentitaet>                                               </zmr:PersonErgebnis>              </zmr:Personendaten>              <zmr:Meldedaten> | 
