hof 20.0.0-beta.7 → 20.0.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.github/workflows/automate-publish.yml +1 -1
  2. package/.github/workflows/automate-tag.yml +1 -1
  3. package/.nyc_output/e2fdc3eb-4fd2-47e0-a392-fe5f665776a4.json +1 -0
  4. package/.nyc_output/processinfo/e2fdc3eb-4fd2-47e0-a392-fe5f665776a4.json +1 -0
  5. package/.nyc_output/processinfo/index.json +1 -1
  6. package/build/lib/mkdir.js +2 -2
  7. package/components/date/index.js +34 -23
  8. package/components/emailer/index.js +49 -41
  9. package/components/emailer/transports/debug.js +1 -2
  10. package/components/summary/index.js +18 -0
  11. package/config/hof-defaults.js +5 -3
  12. package/config/rate-limits.js +20 -0
  13. package/config/sanitisation-rules.js +29 -0
  14. package/controller/base-controller.js +26 -8
  15. package/controller/controller.js +11 -15
  16. package/frontend/govuk-template/build/config.js +1 -1
  17. package/frontend/template-mixins/mixins/template-mixins.js +3 -3
  18. package/frontend/template-partials/translations/src/en/errors.json +12 -0
  19. package/frontend/template-partials/views/rate-limit-error.html +10 -0
  20. package/frontend/themes/gov-uk/client-js/govuk-cookies.js +43 -44
  21. package/frontend/themes/gov-uk/client-js/index.js +5 -3
  22. package/frontend/themes/gov-uk/client-js/skip-to-main.js +18 -17
  23. package/index.js +9 -4
  24. package/lib/router.js +2 -1
  25. package/lib/settings.js +9 -8
  26. package/middleware/errors.js +32 -0
  27. package/middleware/index.js +2 -1
  28. package/middleware/rate-limiter.js +98 -0
  29. package/package.json +5 -6
  30. package/sandbox/apps/sandbox/fields.js +1 -1
  31. package/sandbox/server.js +5 -0
  32. package/transpiler/lib/write-files.js +1 -2
  33. package/utilities/helpers/index.js +16 -1
  34. package/wizard/index.js +1 -0
  35. package/.nyc_output/c8361c72-4aa7-47d0-9f96-d0b84d395382.json +0 -1
  36. package/.nyc_output/processinfo/c8361c72-4aa7-47d0-9f96-d0b84d395382.json +0 -1
@@ -0,0 +1 @@
1
+ {"parent":null,"pid":18892,"argv":["/Users/sulthan/.nvm/versions/node/v16.15.0/bin/node","/Users/sulthan/development/HO/hof/node_modules/.bin/_mocha","test/**/*.spec.js","sandbox/test/**/*.spec.js"],"execArgv":[],"cwd":"/Users/sulthan/development/HO/hof","time":1655401584552,"ppid":18891,"coverageFilename":"/Users/sulthan/development/HO/hof/.nyc_output/e2fdc3eb-4fd2-47e0-a392-fe5f665776a4.json","externalId":"","uuid":"e2fdc3eb-4fd2-47e0-a392-fe5f665776a4","files":["/Users/sulthan/development/HO/hof/model/index.js","/Users/sulthan/development/HO/hof/components/index.js","/Users/sulthan/development/HO/hof/components/address-lookup/index.js","/Users/sulthan/development/HO/hof/components/address-lookup/default-model.js","/Users/sulthan/development/HO/hof/components/address-lookup/defaults.js","/Users/sulthan/development/HO/hof/components/clear-session/index.js","/Users/sulthan/development/HO/hof/components/date/index.js","/Users/sulthan/development/HO/hof/components/date/fields.js","/Users/sulthan/development/HO/hof/components/emailer/index.js","/Users/sulthan/development/HO/hof/components/emailer/email-service.js","/Users/sulthan/development/HO/hof/components/emailer/emailer.js","/Users/sulthan/development/HO/hof/components/emailer/transports/index.js","/Users/sulthan/development/HO/hof/components/emailer/transports/smtp.js","/Users/sulthan/development/HO/hof/components/emailer/transports/ses.js","/Users/sulthan/development/HO/hof/components/emailer/transports/stub.js","/Users/sulthan/development/HO/hof/components/emailer/transports/debug.js","/Users/sulthan/development/HO/hof/components/summary/index.js","/Users/sulthan/development/HO/hof/config/rate-limits.js","/Users/sulthan/development/HO/hof/middleware/rate-limiter.js","/Users/sulthan/development/HO/hof/config/hof-defaults.js","/Users/sulthan/development/HO/hof/controller/base-controller.js","/Users/sulthan/development/HO/hof/controller/formatting/index.js","/Users/sulthan/development/HO/hof/controller/validation/index.js","/Users/sulthan/development/HO/hof/controller/validation/validators.js","/Users/sulthan/development/HO/hof/controller/validation/email.js","/Users/sulthan/development/HO/hof/controller/validation-error.js","/Users/sulthan/development/HO/hof/utilities/index.js","/Users/sulthan/development/HO/hof/utilities/autofill/index.js","/Users/sulthan/development/HO/hof/utilities/autofill/inputs.js","/Users/sulthan/development/HO/hof/utilities/test-data/index.js","/Users/sulthan/development/HO/hof/utilities/countries.js","/Users/sulthan/development/HO/hof/utilities/helpers/index.js","/Users/sulthan/development/HO/hof/utilities/reqres/index.js","/Users/sulthan/development/HO/hof/config/sanitisation-rules.js","/Users/sulthan/development/HO/hof/controller/formatting/formatters.js","/Users/sulthan/development/HO/hof/controller/index.js","/Users/sulthan/development/HO/hof/controller/behaviour-session.js","/Users/sulthan/development/HO/hof/controller/behaviour-hooks.js","/Users/sulthan/development/HO/hof/controller/controller.js","/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/behaviours/country-select.js","/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/index.js","/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/template-mixins.js","/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/render.js","/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/helpers.js","/Users/sulthan/development/HO/hof/index.js","/Users/sulthan/development/HO/hof/frontend/index.js","/Users/sulthan/development/HO/hof/frontend/govuk-template/index.js","/Users/sulthan/development/HO/hof/frontend/govuk-template/build/index.js","/Users/sulthan/development/HO/hof/frontend/govuk-template/build/config.js","/Users/sulthan/development/HO/hof/frontend/template-partials/index.js","/Users/sulthan/development/HO/hof/frontend/template-partials/translations/index.js","/Users/sulthan/development/HO/hof/frontend/themes/index.js","/Users/sulthan/development/HO/hof/frontend/themes/gov-uk/index.js","/Users/sulthan/development/HO/hof/frontend/toolkit/index.js","/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/helpers.js","/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/form-focus.js","/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/progressive-reveal.js","/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/validation.js","/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/character-count.js","/Users/sulthan/development/HO/hof/middleware/index.js","/Users/sulthan/development/HO/hof/middleware/cookies.js","/Users/sulthan/development/HO/hof/middleware/errors.js","/Users/sulthan/development/HO/hof/middleware/not-found.js","/Users/sulthan/development/HO/hof/middleware/deep-translate.js","/Users/sulthan/development/HO/hof/lib/markdown.js","/Users/sulthan/development/HO/hof/lib/router.js","/Users/sulthan/development/HO/hof/wizard/index.js","/Users/sulthan/development/HO/hof/wizard/behaviours/index.js","/Users/sulthan/development/HO/hof/wizard/behaviours/complete.js","/Users/sulthan/development/HO/hof/wizard/util/constants.js","/Users/sulthan/development/HO/hof/lib/helpers.js","/Users/sulthan/development/HO/hof/lib/health.js","/Users/sulthan/development/HO/hof/lib/serve-static.js","/Users/sulthan/development/HO/hof/lib/ga-tag.js","/Users/sulthan/development/HO/hof/lib/sessions.js","/Users/sulthan/development/HO/hof/lib/settings.js","/Users/sulthan/development/HO/hof/lib/logger.js","/Users/sulthan/development/HO/hof/build/index.js","/Users/sulthan/development/HO/hof/config/builder-defaults.js","/Users/sulthan/development/HO/hof/transpiler/index.js","/Users/sulthan/development/HO/hof/transpiler/lib/compile.js","/Users/sulthan/development/HO/hof/transpiler/lib/build.js","/Users/sulthan/development/HO/hof/transpiler/lib/expand-dirs.js","/Users/sulthan/development/HO/hof/transpiler/lib/aggregate.js","/Users/sulthan/development/HO/hof/transpiler/lib/write-files.js","/Users/sulthan/development/HO/hof/model/apis/index.js","/Users/sulthan/development/HO/hof/model/apis/html-to-pdf-converter.js","/Users/sulthan/development/HO/hof/wizard/model.js","/Users/sulthan/development/HO/hof/wizard/middleware/back-links.js","/Users/sulthan/development/HO/hof/wizard/util/helpers.js","/Users/sulthan/development/HO/hof/wizard/middleware/check-complete.js","/Users/sulthan/development/HO/hof/wizard/middleware/check-progress.js","/Users/sulthan/development/HO/hof/wizard/middleware/check-session.js","/Users/sulthan/development/HO/hof/wizard/middleware/csrf.js","/Users/sulthan/development/HO/hof/sandbox/test/_unit/example_app/sections/summary-data-sections.spec.js","/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/sections/summary-data-sections.js","/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/lib/staticAppealStages.js","/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/fields.js","/Users/sulthan/development/HO/hof/sandbox/test/helpers/utilities.js","/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/behaviours/international-number.js","/Users/sulthan/development/HO/hof/lib/encryption.js","/Users/sulthan/development/HO/hof/wizard/middleware/session.js","/Users/sulthan/development/HO/hof/wizard/middleware/session-model.js"]}
@@ -1 +1 @@
1
- {"processes":{"c8361c72-4aa7-47d0-9f96-d0b84d395382":{"parent":null,"children":[]}},"files":{"/Users/sulthan/development/HO/hof/model/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/address-lookup/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/address-lookup/default-model.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/address-lookup/defaults.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/clear-session/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/date/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/date/fields.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/email-service.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/emailer.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/transports/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/transports/smtp.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/transports/ses.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/transports/stub.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/emailer/transports/debug.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/components/summary/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/base-controller.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/formatting/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/validation/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/validation/validators.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/validation/email.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/validation-error.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/formatting/formatters.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/behaviour-session.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/behaviour-hooks.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/controller/controller.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/behaviours/country-select.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/template-mixins.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/render.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/helpers.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/govuk-template/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/govuk-template/build/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/govuk-template/build/config.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/template-partials/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/template-partials/translations/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/themes/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/themes/gov-uk/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/toolkit/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/helpers.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/form-focus.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/progressive-reveal.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/validation.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/character-count.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/middleware/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/middleware/cookies.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/middleware/errors.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/middleware/not-found.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/middleware/deep-translate.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/markdown.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/router.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/behaviours/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/behaviours/complete.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/util/constants.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/helpers.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/health.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/serve-static.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/ga-tag.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/sessions.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/settings.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/config/hof-defaults.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/lib/logger.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/build/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/config/builder-defaults.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/transpiler/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/transpiler/lib/compile.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/transpiler/lib/build.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/transpiler/lib/expand-dirs.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/transpiler/lib/aggregate.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/transpiler/lib/write-files.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/model/apis/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/model/apis/html-to-pdf-converter.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/utilities/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/utilities/autofill/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/utilities/autofill/inputs.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/utilities/test-data/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/utilities/countries.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/utilities/helpers/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/utilities/reqres/index.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/model.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/middleware/back-links.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/util/helpers.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/middleware/check-complete.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/middleware/check-progress.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/middleware/check-session.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/wizard/middleware/csrf.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/sandbox/test/_unit/example_app/sections/summary-data-sections.spec.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/sections/summary-data-sections.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/lib/staticAppealStages.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/fields.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"],"/Users/sulthan/development/HO/hof/sandbox/test/helpers/utilities.js":["c8361c72-4aa7-47d0-9f96-d0b84d395382"]},"externalIds":{}}
1
+ {"processes":{"e2fdc3eb-4fd2-47e0-a392-fe5f665776a4":{"parent":null,"children":[]}},"files":{"/Users/sulthan/development/HO/hof/model/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/address-lookup/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/address-lookup/default-model.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/address-lookup/defaults.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/clear-session/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/date/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/date/fields.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/email-service.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/emailer.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/transports/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/transports/smtp.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/transports/ses.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/transports/stub.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/emailer/transports/debug.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/components/summary/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/config/rate-limits.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/middleware/rate-limiter.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/config/hof-defaults.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/base-controller.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/formatting/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/validation/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/validation/validators.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/validation/email.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/validation-error.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/utilities/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/utilities/autofill/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/utilities/autofill/inputs.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/utilities/test-data/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/utilities/countries.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/utilities/helpers/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/utilities/reqres/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/config/sanitisation-rules.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/formatting/formatters.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/behaviour-session.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/behaviour-hooks.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/controller/controller.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/behaviours/country-select.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/template-mixins.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/render.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/template-mixins/mixins/helpers.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/govuk-template/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/govuk-template/build/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/govuk-template/build/config.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/template-partials/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/template-partials/translations/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/themes/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/themes/gov-uk/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/toolkit/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/helpers.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/form-focus.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/progressive-reveal.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/validation.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/frontend/toolkit/assets/javascript/character-count.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/middleware/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/middleware/cookies.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/middleware/errors.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/middleware/not-found.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/middleware/deep-translate.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/markdown.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/router.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/behaviours/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/behaviours/complete.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/util/constants.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/helpers.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/health.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/serve-static.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/ga-tag.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/sessions.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/settings.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/logger.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/build/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/config/builder-defaults.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/transpiler/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/transpiler/lib/compile.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/transpiler/lib/build.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/transpiler/lib/expand-dirs.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/transpiler/lib/aggregate.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/transpiler/lib/write-files.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/model/apis/index.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/model/apis/html-to-pdf-converter.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/model.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/middleware/back-links.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/util/helpers.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/middleware/check-complete.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/middleware/check-progress.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/middleware/check-session.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/middleware/csrf.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/sandbox/test/_unit/example_app/sections/summary-data-sections.spec.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/sections/summary-data-sections.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/lib/staticAppealStages.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/fields.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/sandbox/test/helpers/utilities.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/sandbox/apps/sandbox/behaviours/international-number.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/lib/encryption.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/middleware/session.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"],"/Users/sulthan/development/HO/hof/wizard/middleware/session-model.js":["e2fdc3eb-4fd2-47e0-a392-fe5f665776a4"]},"externalIds":{}}
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('path');
4
- const mkdirp = require('mkdirp');
4
+ const fs = require('fs');
5
5
 
6
6
  module.exports = file => new Promise((resolve, reject) => {
7
7
  const dir = path.dirname(file);
8
- mkdirp(dir, err => err ? reject(err) : resolve());
8
+ fs.mkdir(dir, {recursive: true}, err => err ? reject(err) : resolve());
9
9
  });
@@ -61,6 +61,37 @@ module.exports = (key, opts) => {
61
61
  dayOptional = true;
62
62
  }
63
63
 
64
+ // take the 3 date parts, padding or defaulting
65
+ // to '01' if applic, then create a date value in the
66
+ // format YYYY-MM-DD. Save to req.body for processing
67
+ const preProcess = (req, res, next) => {
68
+ const parts = getParts(req.body, fields, key);
69
+ if (_.some(parts, part => part !== '')) {
70
+ if (dayOptional && parts.day === '') {
71
+ parts.day = '01';
72
+ } else {
73
+ parts.day = pad(parts.day);
74
+ }
75
+ if (monthOptional && parts.month === '') {
76
+ parts.month = '01';
77
+ } else {
78
+ parts.month = pad(parts.month);
79
+ }
80
+ req.body[key] = `${parts.year}-${parts.month}-${parts.day}`;
81
+ }
82
+ next();
83
+ };
84
+
85
+ // defaultFormatters on the base controller replace '--' with '-' on the process step.
86
+ // This ensures having the correct number of hyphens, so values do not jump from year to month.
87
+ // This should only be done on a partially completed date field otherwise the validation messages break.
88
+ const postProcess = (req, res, next) => {
89
+ const value = req.form.values[key];
90
+ if (value) {
91
+ req.form.values[key] = req.body[key];
92
+ }
93
+ next();
94
+ };
64
95
  // if date field is included in errorValues, extend
65
96
  // errorValues with the individual components
66
97
  const preGetErrors = (req, res, next) => {
@@ -127,35 +158,15 @@ module.exports = (key, opts) => {
127
158
  });
128
159
  };
129
160
 
130
- // take the 3 date parts, padding or defaulting
131
- // to '01' if applic, then create a date value in the
132
- // format YYYY-MM-DD. Save to req.body for processing
133
- const preProcess = (req, res, next) => {
134
- const parts = getParts(req.body, fields, key);
135
- if (_.some(parts, part => part !== '')) {
136
- if (dayOptional && parts.day === '') {
137
- parts.day = '01';
138
- } else {
139
- parts.day = pad(parts.day);
140
- }
141
- if (monthOptional && parts.month === '') {
142
- parts.month = '01';
143
- } else {
144
- parts.month = pad(parts.month);
145
- }
146
- req.body[key] = `${parts.year}-${parts.month}-${parts.day}`;
147
- }
148
- next();
149
- };
150
-
151
161
  // return config extended with hooks
152
162
  return Object.assign({}, options, {
153
163
  hooks: {
164
+ 'pre-process': preProcess,
165
+ 'post-process': postProcess,
154
166
  'pre-getErrors': preGetErrors,
155
167
  'post-getErrors': postGetErrors,
156
168
  'post-getValues': postGetValues,
157
- 'pre-render': preRender,
158
- 'pre-process': preProcess
169
+ 'pre-render': preRender
159
170
  }
160
171
  });
161
172
  };
@@ -17,48 +17,56 @@ module.exports = config => {
17
17
  }
18
18
 
19
19
  return superclass => class EmailBehaviour extends superclass {
20
- successHandler(req, res, callback) {
21
- Promise.resolve()
22
- .then(() => {
23
- debug(`Loading email template from ${config.template}`);
24
- return new Promise((resolve, reject) => {
25
- fs.readFile(config.template, (err, template) => err ? reject(err) : resolve(template.toString('utf8')));
20
+ async successHandler(req, res, next) {
21
+ req.sessionModel.unset('nodemailer-error');
22
+
23
+ try {
24
+ debug(`Loading email template from ${config.template}`);
25
+
26
+ const template = await new Promise((resolve, reject) => {
27
+ return fs.readFile(config.template, (err, resolvedTemplate) => {
28
+ return err ? reject(err) : resolve(resolvedTemplate.toString('utf8'));
26
29
  });
27
- })
28
- .then(template => {
29
- debug('Rendering email content');
30
- const data = config.parse(req.sessionModel.toJSON(), req.translate);
31
- return Hogan.compile(template).render(data);
32
- })
33
- .then(body => {
34
- debug('Building email settings');
35
- const settings = { body };
36
-
37
- if (typeof config.recipient === 'function') {
38
- settings.recipient = config.recipient(req.sessionModel.toJSON());
39
- } else {
40
- settings.recipient = req.sessionModel.get(config.recipient) || config.recipient;
41
- }
42
- if (typeof settings.recipient !== 'string' || !settings.recipient.includes('@')) {
43
- throw new Error('hof-behaviour-emailer: invalid recipient');
44
- }
45
-
46
- if (typeof config.subject === 'function') {
47
- settings.subject = config.subject(req.sessionModel.toJSON(), req.translate);
48
- } else {
49
- settings.subject = config.subject;
50
- }
51
-
52
- return settings;
53
- })
54
- .then(settings => {
55
- debug('Sending email', settings);
56
- return emailer.send(settings);
57
- })
58
- .then(() => {
59
- debug('Email sent successfully');
60
- super.successHandler(req, res, callback);
61
- }, callback);
30
+ });
31
+
32
+ debug('Rendering email content');
33
+
34
+ const data = config.parse(req.sessionModel.toJSON(), req.translate);
35
+
36
+ debug('Building email settings');
37
+
38
+ const settings = { body: Hogan.compile(template).render(data) };
39
+
40
+ if (typeof config.recipient === 'function') {
41
+ settings.recipient = config.recipient(req.sessionModel.toJSON());
42
+ } else {
43
+ settings.recipient = req.sessionModel.get(config.recipient) || config.recipient;
44
+ }
45
+ if (typeof settings.recipient !== 'string' || !settings.recipient.includes('@')) {
46
+ return next(new Error('hof-behaviour-emailer: invalid recipient'));
47
+ }
48
+
49
+ if (typeof config.subject === 'function') {
50
+ settings.subject = config.subject(req.sessionModel.toJSON(), req.translate);
51
+ } else {
52
+ settings.subject = config.subject;
53
+ }
54
+
55
+ debug('Sending email', settings);
56
+
57
+ await emailer.send(settings);
58
+
59
+ debug('Email sent successfully');
60
+
61
+ return super.successHandler(req, res, next);
62
+ } catch (e) {
63
+ if (config.emailerFallback) {
64
+ req.log('error', e.message || e);
65
+ req.sessionModel.set('nodemailer-error', true);
66
+ return super.successHandler(req, res, next);
67
+ }
68
+ return next(e);
69
+ }
62
70
  }
63
71
  };
64
72
  };
@@ -4,7 +4,6 @@
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const cp = require('child_process');
7
- const mkdirp = require('mkdirp');
8
7
 
9
8
  const mimes = {
10
9
  '.gif': 'image/gif',
@@ -12,7 +11,7 @@ const mimes = {
12
11
  };
13
12
 
14
13
  const mkdir = dir => new Promise((resolve, reject) => {
15
- mkdirp(dir, err => err ? reject(err) : resolve());
14
+ fs.mkdir(dir, {recursive: true}, err => err ? reject(err) : resolve());
16
15
  });
17
16
 
18
17
  const cidToBase64 = (h, attachments) => {
@@ -1,6 +1,9 @@
1
1
 
2
2
  'use strict';
3
3
 
4
+ const config = require('../../config/rate-limits');
5
+ const rateLimiter = require('../../middleware/rate-limiter');
6
+
4
7
  const concat = (x, y) => x.concat(y);
5
8
  const flatMap = (f, xs) => xs.map(f).reduce(concat, []);
6
9
 
@@ -215,4 +218,19 @@ module.exports = SuperClass => class extends SuperClass {
215
218
  rows
216
219
  });
217
220
  }
221
+
222
+ validate(req, res, next) {
223
+ if (!config.rateLimits.submissions.active) {
224
+ return super.validate(req, res, next);
225
+ }
226
+ // how do we stop this ballsing up our tests??????
227
+ const options = Object.assign({}, config, { logger: req });
228
+
229
+ return rateLimiter(options, 'submissions')(req, res, err => {
230
+ if (err) {
231
+ return next(err);
232
+ }
233
+ return super.validate(req, res, next);
234
+ });
235
+ }
218
236
  };
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
  /* eslint no-process-env: "off" */
3
+ const rateLimits = require('./rate-limits');
3
4
 
4
5
  const defaults = {
5
6
  appName: process.env.APP_NAME || 'HOF Application',
@@ -19,7 +20,7 @@ const defaults = {
19
20
  host: process.env.HOST || '0.0.0.0',
20
21
  port: process.env.PORT || '8080',
21
22
  env: process.env.NODE_ENV || 'development',
22
- gaTagId: process.env.GA_TAG,
23
+ gaTagId: process.env.GA_TAG || 'Test-GA-Tag',
23
24
  ga4TagId: process.env.GA_4_TAG,
24
25
  gaCrossDomainTrackingTagId: process.env.GDS_CROSS_DOMAIN_GA_TAG,
25
26
  loglevel: process.env.LOG_LEVEL || 'info',
@@ -31,7 +32,8 @@ const defaults = {
31
32
  session: {
32
33
  ttl: process.env.SESSION_TTL || 1800,
33
34
  secret: process.env.SESSION_SECRET || 'changethis',
34
- name: process.env.SESSION_NAME || 'hod.sid'
35
+ name: process.env.SESSION_NAME || 'hod.sid',
36
+ sanitiseInputs: false
35
37
  },
36
38
  apis: {
37
39
  pdfConverter: process.env.PDF_CONVERTER_URL
@@ -39,4 +41,4 @@ const defaults = {
39
41
  serveStatic: process.env.SERVE_STATIC_FILES !== 'false'
40
42
  };
41
43
 
42
- module.exports = defaults;
44
+ module.exports = Object.assign({}, defaults, rateLimits);
@@ -0,0 +1,20 @@
1
+
2
+ module.exports = {
3
+ rateLimits: {
4
+ env: process.env.NODE_ENV,
5
+ requests: {
6
+ active: false,
7
+ windowSizeInMinutes: 5,
8
+ maxWindowRequestCount: 100,
9
+ windowLogIntervalInMinutes: 1,
10
+ errCode: 'DDOS_RATE_LIMIT'
11
+ },
12
+ submissions: {
13
+ active: false,
14
+ windowSizeInMinutes: 10,
15
+ maxWindowRequestCount: 1,
16
+ windowLogIntervalInMinutes: 1,
17
+ errCode: 'SUBMISSION_RATE_LIMIT'
18
+ }
19
+ }
20
+ };
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+ /* eslint no-process-env: "off" */
3
+
4
+ const sanitisationBlacklistArray = {
5
+ // Input will be sanitised using the below rules
6
+ // The key is what we're sanitising out
7
+ // The regex is the rule we used to find them (note some dictate repeating characters)
8
+ // And the replace is what we're replacing that pattern with. Usually nothing sometimes a
9
+ // single character or sometimes a single character followed by a "-"
10
+ '/*': { regex: '\/\\*', replace: '-' },
11
+ '*/': { regex: '\\*\\/', replace: '-' },
12
+ '|': { regex: '\\|', replace: '-' },
13
+ '&&': { regex: '&&+', replace: '&' },
14
+ '@@': { regex: '@@+', replace: '@' },
15
+ '/..;/': { regex: '/\\.\\.;/', replace: '-' }, // Purposely input before ".." as they conflict
16
+ // '..': { regex: '\\.\\.+', replace: '.' }, // Agreed to disable this rule for now unless its specifically required
17
+ '/etc/passwd': { regex: '\/etc\/passwd', replace: '-' },
18
+ 'c:\\': { regex: 'c:\\\\', replace: '-' },
19
+ 'cmd.exe': { regex: 'cmd\\.exe', replace: '-' },
20
+ '<': { regex: '<', replace: '<-' },
21
+ '>': { regex: '>', replace: '>-' },
22
+ '[': { regex: '\\[+', replace: '[-' },
23
+ ']': { regex: '\\]+', replace: ']-' },
24
+ '~': { regex: '~', replace: '~-' },
25
+ '&#': { regex: '&#', replace: '-' },
26
+ '%U': { regex: '%U', replace: '-' }
27
+ };
28
+
29
+ module.exports = sanitisationBlacklistArray;
@@ -8,6 +8,8 @@ const debug = require('debug')('hmpo:form');
8
8
  const dataFormatter = require('./formatting');
9
9
  const dataValidator = require('./validation');
10
10
  const ErrorClass = require('./validation-error');
11
+ const Helpers = require('../utilities').helpers;
12
+ const sanitisationBlacklistArray = require('../config/sanitisation-rules');
11
13
 
12
14
  module.exports = class BaseController extends EventEmitter {
13
15
  constructor(options) {
@@ -69,6 +71,7 @@ module.exports = class BaseController extends EventEmitter {
69
71
  this._configure.bind(this),
70
72
  this._process.bind(this),
71
73
  this._validate.bind(this),
74
+ this._sanitize.bind(this),
72
75
  this._getHistoricalValues.bind(this),
73
76
  this.saveValues.bind(this),
74
77
  this.successHandler.bind(this),
@@ -162,6 +165,28 @@ module.exports = class BaseController extends EventEmitter {
162
165
  return validator(key, req.form.values[key], req.form.values, emptyValue);
163
166
  }
164
167
 
168
+ _sanitize(req, res, callback) {
169
+ // Sanitisation could be disabled in the config
170
+ if(!this.options.sanitiseInputs) return callback();
171
+
172
+ // If we don't have any data, no need to progress
173
+ if(!_.isEmpty(req.form.values)) {
174
+ Object.keys(req.form.values).forEach(function (property, propertyIndex) {
175
+ // If it's not a string, don't sanitise it
176
+ if(_.isString(req.form.values[property])) {
177
+ // For each property in our form data
178
+ Object.keys(sanitisationBlacklistArray).forEach(function (blacklisted, blacklistedIndex) {
179
+ const blacklistedDetail = sanitisationBlacklistArray[blacklisted];
180
+ const regexQuery = new RegExp(blacklistedDetail.regex, 'gi');
181
+ // Will perform the required replace based on our passed in regex and the replace string
182
+ req.form.values[property] = req.form.values[property].replace(regexQuery, blacklistedDetail.replace);
183
+ });
184
+ }
185
+ });
186
+ }
187
+ return callback();
188
+ }
189
+
165
190
  _process(req, res, callback) {
166
191
  req.form.values = req.form.values || {};
167
192
  const formatter = dataFormatter(
@@ -213,16 +238,9 @@ module.exports = class BaseController extends EventEmitter {
213
238
  }
214
239
 
215
240
  _getForkTarget(req, res) {
216
- function evalCondition(condition) {
217
- return _.isFunction(condition) ?
218
- condition(req, res) :
219
- condition.value === (req.form.values[condition.field] ||
220
- (req.form.historicalValues && req.form.historicalValues[condition.field]));
221
- }
222
-
223
241
  // If a fork condition is met, its target supercedes the next property
224
242
  return req.form.options.forks.reduce((result, value) =>
225
- evalCondition(value.condition) ?
243
+ Helpers.isFieldValueInPageOrSessionValid(req, res, value.condition) ?
226
244
  value.target :
227
245
  result
228
246
  , req.form.options.next);
@@ -4,6 +4,7 @@ const _ = require('lodash');
4
4
  const i18nLookup = require('i18n-lookup');
5
5
  const Mustache = require('mustache');
6
6
  const BaseController = require('./base-controller');
7
+ const Helpers = require('../utilities').helpers;
7
8
 
8
9
  const omitField = (field, req) => field.useWhen && (typeof field.useWhen === 'string'
9
10
  ? req.sessionModel.get(field.useWhen) !== 'true'
@@ -54,12 +55,7 @@ module.exports = class Controller extends BaseController {
54
55
 
55
56
  // If a form condition is met, its target supercedes the next property
56
57
  next = _.reduce(forks, (result, value) => {
57
- const evalCondition = condition => _.isFunction(condition) ?
58
- condition(req, res) :
59
- condition.value === (req.form.values[condition.field] ||
60
- (req.form.historicalValues && req.form.historicalValues[condition.field]));
61
-
62
- if (evalCondition(value.condition)) {
58
+ if (Helpers.isFieldValueInPageOrSessionValid(req, res, value.condition)) {
63
59
  if (value.continueOnEdit) {
64
60
  req.form.options.continueOnEdit = true;
65
61
  }
@@ -128,22 +124,22 @@ module.exports = class Controller extends BaseController {
128
124
  }
129
125
 
130
126
  getFirstFormItem(fields) {
131
- let firstFieldKey
127
+ let firstFieldKey;
132
128
  if (_.size(fields)) {
133
- firstFieldKey = Object.keys(fields)[0]
129
+ firstFieldKey = Object.keys(fields)[0];
134
130
  }
135
131
  return firstFieldKey | 'main-content';
136
132
  }
137
133
 
138
- getHeader(route, lookup, locals){
134
+ getHeader(route, lookup, locals) {
139
135
  return lookup(`pages.${route}.header`, locals);
140
136
  }
141
137
 
142
- getCaptionHeading(route, lookup, locals){
138
+ getCaptionHeading(route, lookup, locals) {
143
139
  return lookup(`pages.${route}.captionHeading`, locals);
144
140
  }
145
141
 
146
- getSubHeading(route, lookup, locals){
142
+ getSubHeading(route, lookup, locals) {
147
143
  return lookup(`pages.${route}.subHeading`, locals);
148
144
  }
149
145
 
@@ -171,14 +167,14 @@ module.exports = class Controller extends BaseController {
171
167
  if (req.form && req.form.options && req.form.options.fields) {
172
168
  const field = req.form.options.fields[key];
173
169
  // get first option for radios
174
- if(field.mixin === 'radio-group') {
175
- req.form.errors[key].errorLinkId = key + "-" + field.options[0];
170
+ if (field.mixin === 'radio-group') {
171
+ req.form.errors[key].errorLinkId = key + '-' + field.options[0];
172
+ // eslint-disable-next-line brace-style
176
173
  }
177
174
  // get first field for date input control
178
175
  else if (field && field.controlType === 'date-input') {
179
176
  req.form.errors[key].errorLinkId = key + '-day';
180
- }
181
- else {
177
+ } else {
182
178
  req.form.errors[key].errorLinkId = key;
183
179
  }
184
180
  }
@@ -4,7 +4,7 @@ module.exports = {
4
4
  htmlLang: '{{htmlLang}}',
5
5
  assetPath: '{{govukAssetPath}}',
6
6
  afterHeader: '{{$afterHeader}}{{/afterHeader}}',
7
- bodyClasses: '{{$bodyClasses}}{{/bodyClasses}}',
7
+ bodyClasses: '{{$bodyClasses}}{{/bodyClasses}}',
8
8
  bodyStart: '{{$bodyStart}}{{/bodyStart}}',
9
9
  bodyEnd: '{{$bodyEnd}}{{/bodyEnd}}',
10
10
  content: '{{$main}}{{/main}}',
@@ -431,8 +431,8 @@ module.exports = function (options) {
431
431
  year: autocomplete + '-year'
432
432
  };
433
433
  }
434
- const isRequired = field.validate ? field.validate.indexOf('required') > -1 : false;
435
- const formGroupClassName = (field.formGroup && field.formGroup.className) ? field.formGroup.className : ''
434
+ const isThisRequired = field.validate ? field.validate.indexOf('required') > -1 : false;
435
+ const formGroupClassName = (field.formGroup && field.formGroup.className) ? field.formGroup.className : '';
436
436
  const classNameDay = (field.controlsClass && field.controlsClass.day) ? field.controlsClass.day : 'govuk-date-input__input govuk-input--width-2';
437
437
  const classNameMonth = (field.controlsClass && field.controlsClass.month) ? field.controlsClass.month : 'govuk-date-input__input govuk-input--width-2';
438
438
  const classNameYear = (field.controlsClass && field.controlsClass.year) ? field.controlsClass.year : 'govuk-date-input__input govuk-input--width-4';
@@ -440,7 +440,7 @@ module.exports = function (options) {
440
440
  const parts = [];
441
441
 
442
442
  if (isExact) {
443
- const dayPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-day', { pattern: '[0-9]*', min: 1, max: 31, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.day, formGroupClassName, className: classNameDay, isRequired }));
443
+ const dayPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-day', { pattern: '[0-9]*', min: 1, max: 31, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.day, formGroupClassName, className: classNameDay, isThisRequired }));
444
444
  parts.push(dayPart);
445
445
  }
446
446
 
@@ -14,5 +14,17 @@
14
14
  "cookies-required": {
15
15
  "title": "Cookies are required to use this service",
16
16
  "message": "Cookies are required in order to use this service.<br /><br /> Please <a href=\"http://www.aboutcookies.org/how-to-control-cookies/\" rel=\"external\">enable cookies</a> and try again. Find out <a href=\"/cookies\">how to we use cookies</a>."
17
+ },
18
+ "ddos-rate-limit": {
19
+ "title": "Too many requests submitted",
20
+ "message": "You have submitted too many requests in quick succession.",
21
+ "pre-time-to-wait": "Please try again in ",
22
+ "post-time-to-wait": " minutes."
23
+ },
24
+ "submission-rate-limit": {
25
+ "title": "Too many submissions",
26
+ "message": "You have submitted too many applications in a short space of time.",
27
+ "pre-time-to-wait": "Please try again in ",
28
+ "post-time-to-wait": " minutes."
17
29
  }
18
30
  }
@@ -0,0 +1,10 @@
1
+ {{<layout}}
2
+ {{$header}}
3
+ {{content.title}}
4
+ {{/header}}
5
+ {{$content}}
6
+ <p>{{content.message}}</p>
7
+ <p>{{content.preTimeToWait}}{{content.timeToWait}}{{content.postTimeToWait}}</p>
8
+ <a href="/" class="button" role="button">{{#t}}buttons.try-again{{/t}}</a>
9
+ {{/content}}
10
+ {{/layout}}