diff options
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java')
-rw-r--r-- | eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java | 214 |
1 files changed, 214 insertions, 0 deletions
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 new file mode 100644 index 00000000..83fdf771 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java @@ -0,0 +1,214 @@ +/* + * Copyright 2021 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.tasks; + +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +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.dao.MatchedPersonResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.InvalidUserInputException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; +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.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 lombok.extern.slf4j.Slf4j; + + +/** + * Task receives the response of {@link GenerateAustrianResidenceGuiTask} and handles it. + * This corresponds to Steps 17B, 18, 19 in the eIDAS Matching Concept. + * Input: + * <ul> + * <li>{@link Constants#DATA_SIMPLE_EIDAS} initial login data from user</li> + * <li>{@link Constants#DATA_INTERMEDIATE_RESULT} results from search in registers with personIdentifier</li> + * </ul> + * Output: + * <ul> + * <li>{@link Constants#DATA_RESULT_MATCHING_BPK} if one register result found</li> + * </ul> + * Transitions: + * <ul> + * <li>{@link CreateNewErnpEntryTask} 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> + * </ul> + * + * @author amarsalek + * @author ckollmann + * @author tlenz + */ +@Slf4j +@Component("ReceiveAustrianResidenceGuiResponseTask") +public class ReceiveAustrianResidenceGuiResponseTask extends AbstractAuthServletTask { + + 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 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 { + log.trace("Starting ReceiveAustrianResidenceGuiResponseTask"); + + UserInput input = parseHtmlInput(request); + if (!input.isFormerResidenceAvailable()) { + moveToNextTask(executionContext); + return; + + } + + //TODO: Here, we need an error handling an can not stop full process if form input was invalid + //TODO: check minimum form elements + /*TODO: maybe we can switch to custom controller and use WebMVC form-binding feature. + * Binding element can be add as attribute to this request + */ + if (input.getStreet().isEmpty() || input.getCity().isEmpty() || input.getZipcode().isEmpty()) { + // HTML form should ensure that mandatory fields are set => this should never happen + throw new TaskExecutionException(pendingReq, "Invalid user input", + new InvalidUserInputException("module.eidasauth.matching.06")); + + } + + + + try { + SimpleEidasData eidasData = MatchingTaskUtils.getInitialEidasData(pendingReq); + RegisterStatusResults initialSearchResult = MatchingTaskUtils.getIntermediateMatchingResult(pendingReq); + + 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); + + } 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)); + + } + + } catch (EaafStorageException e) { + log.error("Search with residency data failed", e); + throw new TaskExecutionException(pendingReq, "Search with residency data failed", e); + + } + } + + private void compareSearchResultWithInitialData(ExecutionContext executionContext, + RegisterStatusResults residencyResult, SimpleEidasData eidasData) + throws TaskExecutionException, EaafStorageException { + try { + /*TODO: check 'equalsRegisterData' because this method maybe this method evaluate to an invalid result. + * See TODO in methods body + */ + if (eidasData.equalsRegisterData(residencyResult.getResult())) { + // update register information + registerSearchService.step7aKittProcess(residencyResult, eidasData); + + // store search result to re-used in CreateIdentityLink step, because there we need bPK and MDS + MatchingTaskUtils.storeFinalMatchingResult(pendingReq, + MatchedPersonResult.generateFormMatchingResult( + residencyResult.getResult(), eidasData.getCitizenCountryCode())); + + } else { + moveToNextTask(executionContext); + + } + + } catch (WorkflowException 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) { + Enumeration<String> reqParamNames = request.getParameterNames(); + UserInput result = new UserInput(); + 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)); + + } else if (PARAM_STREET.equalsIgnoreCase(paramName)) { + result.setStreet(escaped); + + } else if (PARAM_CITY.equalsIgnoreCase(paramName)) { + result.setCity(escaped); + + } else if (PARAM_ZIPCODE.equalsIgnoreCase(paramName)) { + result.setZipcode(escaped); + + } + } + return result; + + } + +} |