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.mockito.ArgumentMatchers.eq; import java.math.BigInteger; import java.util.Arrays; import java.util.Collections; 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.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; 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.google.common.collect.Lists; import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.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.log.statistic.DetailedMatchtingStatistic; 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.utils.MatchingTaskUtils; import at.gv.egiz.eaaf.core.api.IRequestStorage; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; 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 ReceiveAustrianResidenceGuiResponseTaskTest { @Autowired protected MsConnectorDummyConfigMap authConfig; @Autowired(required = true) protected IRequestStorage requestStoreage; @MockBean private RegisterSearchService registerSearchService; private ReceiveAustrianResidenceGuiResponseTask task; private ExecutionContext executionContext; private MockHttpServletRequest httpReq; private MockHttpServletResponse httpResp; private TestRequestImpl pendingReq; /** * jUnit test set-up. * * @throws Exception In case of an set-up error */ @Before public void setUp() throws Exception { executionContext = new ExecutionContextImpl(); task = new ReceiveAustrianResidenceGuiResponseTask(registerSearchService); task.setRequestStoreage(requestStoreage); 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(); mockRegisterSearch(userInput, registerSearchResult, eidasData); MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); httpReq.setParameter(ReceiveAustrianResidenceGuiResponseTask.HTTP_PARAM_NO_RESIDENCE, "true"); task.execute(pendingReq, executionContext); assertEquals("Transition To RequestInserErnp", true, executionContext.get(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK)); assertEquals("Transition To AddressSearchForm", false, executionContext.get(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK)); assertNull("matching failed flag", executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED)); 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 RequestInserErnp", false, executionContext.get(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK)); assertEquals("Transition To AddressSearchForm", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_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)); DetailedMatchtingStatistic entry = MatchingTaskUtils.getDetailedMatchingStatistic(pendingReq); assertNotNull("statisticLogEntry", entry); assertEquals("registerSearchCount", 0, entry.getAddressSearchUsed()); } @Test public void noRegisterResult() throws Exception { AdresssucheOutput userInput = setupUserInput(); SimpleEidasData eidasData = setupEidasData(); RegisterStatusResults registerSearchResult = buildEmptyResult(); mockRegisterSearch(userInput, registerSearchResult, eidasData); MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); task.execute(pendingReq, executionContext); assertEquals("Transition To RequestInserErnp", false, executionContext.get(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK)); assertEquals("Transition To AddressSearchForm", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_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)); DetailedMatchtingStatistic entry = MatchingTaskUtils.getDetailedMatchingStatistic(pendingReq); assertNotNull("statisticLogEntry", entry); assertEquals("registerSearchCount", 1, entry.getAddressSearchUsed()); } @Test 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)); MatchedPersonResult matchingResult = MatchingTaskUtils.getFinalMatchingResult(pendingReq); assertNotNull("no final matching result", matchingResult); validateMatchedPerson(matchingResult, registerSearchResult); } @Test 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); // 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 { AdresssucheOutput userInput = setupUserInput(); SimpleEidasData eidasData = setupEidasData(); RegisterStatusResults registerSearchResult = buildResultWithTwoMatches(); MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerSearchResult); mockRegisterSearch(userInput, registerSearchResult, eidasData); task.execute(pendingReq, executionContext); assertEquals("Transition To RequestInserErnp", false, executionContext.get(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK)); assertEquals("Transition To AddressSearchForm", true, executionContext.get(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_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)); } @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))).thenReturn(registerSearchResult); } @NotNull private RegisterStatusResults buildEmptyResult() { return new RegisterStatusResults(new RegisterOperationStatus(generateRandomProcessId(), true), 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(), true), Collections.singletonList(registerResult), Collections.emptyList()); } @NotNull private RegisterStatusResults buildResultWithTwoMatches() { List results = Lists.newArrayList(buildRandomRegisterResult(), buildRandomRegisterResult()); return new RegisterStatusResults(new RegisterOperationStatus(generateRandomProcessId(), true), 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; } }