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

Sign up to get free protection for your applications and to get access to all the features.
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}}