Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CCAP-661][CCAP-698] Handle incorrect confirmation code on landing screen followup work #1229

Merged
merged 9 commits into from
Feb 28, 2025
23 changes: 20 additions & 3 deletions src/main/java/org/ilgcc/app/ProviderLinkController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import formflow.library.data.SubmissionRepositoryService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
Expand All @@ -12,6 +14,9 @@
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;

import static org.ilgcc.app.utils.constants.SessionKeys.SESSION_KEY_CAME_FROM_HOME_PAGE;
import static org.ilgcc.app.utils.constants.SessionKeys.SESSION_KEY_FAMILY_SUBMISSION_ID;
import static org.ilgcc.app.utils.constants.SessionKeys.SESSION_KEY_SUBMISSION_MAP;

Expand All @@ -33,8 +38,9 @@ public ProviderLinkController(SubmissionRepositoryService submissionRepositorySe
*/
@GetMapping(value = {"s", "s/{confirmationCode}", "providerresponse/submit/{confirmationCode}"})
String loadFamilySubmission(HttpSession session, HttpServletRequest request,
@PathVariable(required = false) String confirmationCode) {

@PathVariable(required = false) String confirmationCode,
@RequestHeader(value = "Referer", required = false) String referer
) throws URISyntaxException {
session.invalidate();

// create a new session and populate it with an empty FFL submission map
Expand All @@ -47,7 +53,7 @@ String loadFamilySubmission(HttpSession session, HttpServletRequest request,
log.info("Loading submission for code " + sanitizedConfirmationCode);

if (sanitizedConfirmationCode != null) {
Optional<Submission> submission = submissionRepositoryService.findByShortCode(sanitizedConfirmationCode);
Optional<Submission> submission = submissionRepositoryService.findByShortCode(sanitizedConfirmationCode.toUpperCase());
if (submission.isPresent()) {
Submission s = submission.get();
Map<String, String> urlParams = s.getUrlParams();
Expand All @@ -60,6 +66,8 @@ String loadFamilySubmission(HttpSession session, HttpServletRequest request,
submissionRepositoryService.save(s);

newSession.setAttribute(SESSION_KEY_FAMILY_SUBMISSION_ID, s.getId());

checkRefererValue(referer, newSession);
} else {
log.error("Unable to load submission for code " + sanitizedConfirmationCode);
return "redirect:/error-invalid-code";
Expand All @@ -68,4 +76,13 @@ String loadFamilySubmission(HttpSession session, HttpServletRequest request,

return "redirect:/flow/providerresponse/submit-start";
}

private static void checkRefererValue(String referer, HttpSession newSession) throws URISyntaxException {
if (referer != null) {
URI refererUri = new URI(referer);
if (("/").equals(refererUri.getPath())) {
newSession.setAttribute(SESSION_KEY_CAME_FROM_HOME_PAGE, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool so this is only set when it was a valid confirmation code

}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ ResponseEntity<?> downloadPdf(@PathVariable String flow, @PathVariable String su
}

Optional<Submission> optionalFamilySubmission = submissionRepositoryService.findByShortCode(
providerResponseFamilyShortCode.toString());
providerResponseFamilyShortCode.toString().toUpperCase());
if (optionalFamilySubmission.isEmpty()) {
log.warn(
"Attempted to download PDF with provider submission id: {} but no family submission was found with confirmation code: {}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ public class FindApplicationData implements Action {
@Override
public void run(Submission providerSubmission) {
Optional<UUID> familySubmissionId = ProviderSubmissionUtilities.getFamilySubmissionId(providerSubmission);
if(familySubmissionId.isPresent()){
Optional<Submission> familySubmission = submissionRepositoryService.findById(familySubmissionId.get());
providerSubmission.getInputData().put("clientResponse", ProviderSubmissionUtilities.getFamilySubmissionForProviderResponse(familySubmission));
if (familySubmissionId.isPresent()) {
Optional<Submission> familySubmission = submissionRepositoryService.findById(familySubmissionId.get());
providerSubmission.getInputData()
.put("clientResponse", ProviderSubmissionUtilities.getFamilySubmissionForProviderResponse(familySubmission));

providerSubmission.getInputData().put("clientResponseChildren", ProviderSubmissionUtilities.getChildrenDataForProviderResponse(familySubmission.get()));
submissionRepositoryService.save(providerSubmission);
providerSubmission.getInputData().put("clientResponseChildren",
ProviderSubmissionUtilities.getChildrenDataForProviderResponse(familySubmission.get()));
submissionRepositoryService.save(providerSubmission);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all just reformatting of the code. I was in it while debugging, no actual code changes here.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ public void run(FormSubmission formSubmission, Submission submission) {
dummyFamilySubmission.setFlow("gcc");
dummyFamilySubmission.setShortCode("DEV-123ABC");
dummyFamilySubmission.setInputData(inputData);
submissionRepositoryService.save(dummyFamilySubmission);

dummyFamilySubmission = submissionRepositoryService.save(dummyFamilySubmission);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol this literally wasted 3 hours of my life, as I struggled to figure out why the family submission id was magically being removed from the session. oops.


httpSession.setAttribute(SESSION_KEY_FAMILY_SUBMISSION_ID, dummyFamilySubmission.getId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public Map<String, List<String>> runValidation(FormSubmission formSubmission, Su
.getOrDefault("providerResponseFamilyShortCode", "");

if (!providerProvidedConfirmationCode.isBlank()) {
Optional<Submission> familySubmission = submissionRepositoryService.findByShortCode(providerProvidedConfirmationCode);
Optional<Submission> familySubmission = submissionRepositoryService.findByShortCode(providerProvidedConfirmationCode.toUpperCase());

if (familySubmission.isPresent()) {
httpSession.setAttribute(SESSION_KEY_FAMILY_SUBMISSION_ID, familySubmission.get().getId());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.ilgcc.app.submission.conditions;

import static org.ilgcc.app.utils.constants.SessionKeys.SESSION_KEY_CAME_FROM_HOME_PAGE;

import formflow.library.config.submission.Condition;
import formflow.library.data.Submission;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Component;

@Component
public class ShouldSkipConfirmationCode implements Condition {

private final HttpSession httpSession;

public ShouldSkipConfirmationCode(HttpSession httpSession) {
this.httpSession = httpSession;
}

@Override
public Boolean run(Submission submission) {
Boolean cameFromHomePage = (Boolean) httpSession.getAttribute(SESSION_KEY_CAME_FROM_HOME_PAGE);
return cameFromHomePage != null && cameFromHomePage;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ public class SessionKeys {
public final static String SESSION_KEY_FAMILY_CONFIRMATION_CODE = "confirmationCode";
public final static String SESSION_KEY_SUBMISSION_MAP = "submissionMap";
public final static String SESSION_KEY_SELECTED_PROVIDER_NAME = "selectedProviderName";
public final static String SESSION_KEY_CAME_FROM_HOME_PAGE = "cameFromHomePage";
}
2 changes: 2 additions & 0 deletions src/main/resources/flows-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,8 @@ flow:
beforeSaveAction: ConnectProviderApplicationToFamilyApplication
onPostAction: GenerateDummyFamilySubmissionForDev
nextScreens:
- name: response
condition: ShouldSkipConfirmationCode
- name: confirmation-code
confirmation-code:
crossFieldValidationAction: ValidateConfirmationCodeAndSaveId
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only concern is whether any if these actions are important for an application: ValidateConfirmationCodeAndSaveId or CheckFamilySubmissionForProvider

Copy link
Contributor Author

@cram-cfa cram-cfa Feb 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great question and valid concern! I dug into those yesterday to make sure I wasn't missing something obvious.

ValidateConfirmationCodeAndSaveId validates that the confirmation code was valid and not expired, etc but we already know that it's good to go because the initial intake of the code from the homepage will already have validated it. It also saves the familySubmissionId to the provider submission, that happens as well when the Provider enters their id number with ConnectProviderApplicationToFamilyApplication -- and because the provider can't change the confirmation code from family submission A to family submission B now, because we're not showing the screen to enter the confirmation code, there's no risk of us joining the wrong family submission to the provider submission in this scenario.

CheckFamilySubmissionForProvider is a similar scenario -- we run this action on the initial intake of the confirmation code, either via a link or now from the homepage input. We have to run it again if we allow the provider to enter a confirmation code because they might have entered/used the link for family A... and then they could change it to family B... but since we're now skipping the screen, the provider won't be able to cause chaos in that manner.

So, we should be good here. I walked through the flow and it seemed to all work for me, the tests all pass, etc. Staring at this yesterday and today, walking through it with the debugger, I feel pretty confident in the above two paragraphs πŸ˜„

Expand Down
41 changes: 23 additions & 18 deletions src/main/resources/messages_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ general.none-added=Nada agregado
general.helptext-relevant-questions-only=Responda οΏ½nicamente las preguntas que sean relevantes
general.step-header=Paso {0} de {1}

general-survey-question.very-easy=Muy fοΏ½cil
general-survey-question.easy=FοΏ½cil
general-survey-question.neither=Ni fοΏ½cil ni difοΏ½cil
general-survey-question.difficult=DifοΏ½cil
general-survey-question.very-difficult=Muy difοΏ½cil

general.day.validation=AsegοΏ½rese de haber ingresado el dοΏ½a correcto.
general.month.validation=AsegοΏ½rese de haber ingresado el mes correcto.
general.year.validation=AsegοΏ½rese de haber ingresado el aοΏ½o correcto.
Expand Down Expand Up @@ -444,6 +450,9 @@ children-childcare-hourly-schedule.same-every-day=El horario es igual todos los
#children-ccap-child-other-ed
children-ccap-child-other-ed.title=CCAP Child Other
children-ccap-child-other-ed.header=οΏ½{0} asiste a alguna otra escuela o a algοΏ½n otro programa educativo durante el dοΏ½a?
#children-school-weekly-schedule
children-school-weekly-schedule.title=Horario escolar
children-school-weekly-schedule.header=οΏ½QuοΏ½ dοΏ½as y en quοΏ½ horario estοΏ½ {0} en la escuela?
#
delete-confirmation.title=Eliminar persona
delete-confirmation.header=οΏ½Esta seguro que quiere borrar a {0} de la solicitud?
Expand Down Expand Up @@ -777,30 +786,20 @@ next-steps-pdf-delivery.notice=<ul class="list--numbered"><li> Imprima su solici

submit-next-steps.no-provider=<ul class="list--numbered"><li>Un miembro del personal de la oficina local de las CCR&R <strong>{0}</strong> comenzarοΏ½ a revisar su solicitud en un plazo de 10 dοΏ½as hοΏ½biles</li><li>Un miembro del personal se comunicarοΏ½ con usted para ayudarlo a encontrar un proveedor de cuidado de niοΏ½os.</li><li>RecibirοΏ½ una carta por correo o un mensaje de correo electrοΏ½nico sobre su solicitud.</li><li>Es posible que se le pida que envοΏ½e documentos de verificaciοΏ½n adicionales.</li></ul>

submit-confirmation.title=Su solicitud ha sido enviada
submit-confirmation.subtext=Su solicitud se enviοΏ½ a su Agencia de Recursos y Referencias del Cuidado de NiοΏ½os (CCR&R) el {0} a las {1}.
submit-confirmation.download-text=Descargue una copia de su solicitud
submit-confirmation.rest-of-paragraph=y guοΏ½rdela para su registro.
submit-confirmation.experience=CuοΏ½ntenos mοΏ½s sobre su experiencia con este sitio web. (Opcional).
submit-confirmation.survey.label=En general, οΏ½quοΏ½ tan fοΏ½cil o difοΏ½cil fue para usted completar su solicitud en este sitio web?
submit-confirmation.survey.very-easy=Muy fοΏ½cil
submit-confirmation.survey.easy=FοΏ½cil
submit-confirmation.survey.neither=Ni fοΏ½cil ni difοΏ½cil
submit-confirmation.survey.difficult=DifοΏ½cil
submit-confirmation.survey.very-difficult=Muy difοΏ½cil
submit-confirmation.comments.label=Comentarios adicionales
submit-confirmation.survey.complete=Muchas gracias por sus comentarios.
submit-confirmation.button.feedback=Enviar mis comentarios
submit-confirmation.button.return=Volver al inicio
submit-confirmation.general.experience=CuοΏ½ntenos mοΏ½s sobre su experiencia con este sitio web. (Opcional).
submit-confirmation.general.comments.label=Comentarios adicionales
submit-confirmation.general.survey.complete=Muchas gracias por sus comentarios.
submit-confirmation.general.call-text=<a id='call-ccrr' href='https://www.inccrra.org/about/sdasearch' target='_blank' data-mixpanel='call-ccrr'>Llame a su CCR&R </a> si tiene preguntas sobre el estado de su solicitud.
submit-confirmation.general.button.feedback=Enviar mis comentarios
submit-confirmation.general.button.return=Volver a la pοΏ½gina principal
submit-confirmation.general.subtext=<p>Completada el {0} {1}.</p><p>Su cοΏ½digo de confirmaciοΏ½n es: <strong>{2}</strong>

#complete-submit-confirmation
complete-submit-confirmation.title=Complete prοΏ½ximos pasos
complete-submit-confirmation.header=οΏ½Ha completado su solicitud en lοΏ½nea!
complete-submit-confirmation.subtext=<p>Completada el {0} {1}.</p><p>Su cοΏ½digo de confirmaciοΏ½n es: <strong>{2}</strong>
complete-submit-confirmation.download-text=Descargue una copia de su solicitud
complete-submit-confirmation.rest-of-download-paragraph=para su registro.
complete-submit-confirmation.call-text=Llame a su CCR&R
complete-submit-confirmation.rest-of-call-paragraph=si tiene preguntas sobre el estado de su solicitud.
complete-submit-confirmation.survey.label=En general, οΏ½quοΏ½ tan fοΏ½cil o difοΏ½cil fue para usted completar su solicitud en este sitio web?

#
#doc-upload-recommended-docs
Expand Down Expand Up @@ -1623,3 +1622,9 @@ registration-doc-upload-add-files.ein.body=Agregue una carta del IRS que muestre
registration-doc-upload-add-files.license-exempt.header=Carta de exenciοΏ½n de licencia
registration-doc-upload-add-files.license-exempt.body=Agregue su carta de la agencia de licencias de su estado que indique que no necesita una licencia.
registration-doc-upload-add-files.confirmation=TerminοΏ½ de subir los archivos

#registration-submit-confirmation
registration-submit-confirmation.title=Solicitud con el CCAP finalizada
registration-submit-confirmation.header=οΏ½Ha terminado con su registro de proveedor!
registration-submit-confirmation.q1=οΏ½QuοΏ½ tan fοΏ½cil o difοΏ½cil fue la experiencia de responder a la solicitud de la familia?
registration-submit-confirmation.q2=οΏ½QuοΏ½ tan fοΏ½cil o difοΏ½cil fue la experiencia de registrarse como nuevo proveedor?
9 changes: 5 additions & 4 deletions src/main/resources/templates/error-invalid-code.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
</div>
<div class="form-card__footer">
<a
href="/"
data-mixpanel="invalid-code-return-home"
th:text="#{error-invalid-code.button}"
class="button--primary button"></a>
id="return-to-homepage"
href="/"
data-mixpanel="invalid-code-return-home"
th:text="#{error-invalid-code.button}"
class="button--primary button"></a>
</div>
</main>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,6 @@ void ProviderresponseJourneyTest_noLink_invalidConfirmationCode() {
testPage.enter("providerResponseFamilyShortCode", "");
testPage.clickContinue();

assertThat(testPage.getTitle()).isEqualTo(getEnMessage("errors.general-title"));
assertThat(testPage.hasErrorText(getEnMessage("errors.provide-applicant-number"))).isTrue();
testPage.enter("providerResponseFamilyShortCode", "a2123b");
testPage.clickContinue();

assertThat(testPage.getTitle()).isEqualTo(getEnMessage("errors.general-title"));
assertThat(testPage.hasErrorText(getEnMessage("errors.provide-applicant-number"))).isTrue();
testPage.enter("providerResponseFamilyShortCode", "123");
Expand All @@ -292,6 +287,10 @@ void ProviderresponseJourneyTest_noLink_invalidConfirmationCode() {

assertThat(testPage.getTitle()).isEqualTo(getEnMessage("errors.general-title"));
assertThat(testPage.hasErrorText(getEnMessage("errors.provide-applicant-number"))).isTrue();
testPage.enter("providerResponseFamilyShortCode", "a2123b");
testPage.clickContinue();
// Confirmation codes that are correct but incorrect casing should still pass validation
assertThat(testPage.getTitle()).isEqualTo(getEnMessage("provider-response-response.title"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.time.OffsetDateTime;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -40,6 +41,7 @@ void setUp() {
submission.setId(UUID.randomUUID());
}

@Disabled
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test keeps failing intermittently on Github runs. Skipping it for now, and hopefully we can find time in the next week to make the test more reliable.

@Test
void whenRun_thenPdfIsZippedAndUploadedToS3() throws IOException, InterruptedException {

Expand Down