hof 22.8.4 → 22.9.0-beta.v1

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 (325) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +30 -0
  3. package/config/hof-defaults.js +6 -1
  4. package/frontend/govuk-template/govuk_template_generated.html +102 -0
  5. package/frontend/template-partials/views/layout.html +2 -8
  6. package/frontend/themes/gov-uk/styles/_cookie-banner.scss +0 -3
  7. package/lib/settings.js +1 -0
  8. package/package/.eslintignore +1 -0
  9. package/package/CHANGELOG.md +232 -0
  10. package/package/LICENSE +21 -0
  11. package/package/README.md +1887 -0
  12. package/package/bin/hof-build +10 -0
  13. package/package/bin/hof-transpiler +12 -0
  14. package/package/build/helpers/importer.js +29 -0
  15. package/package/build/helpers/local.js +35 -0
  16. package/package/build/helpers/resolver/import.js +32 -0
  17. package/package/build/helpers/resolver/nearest-package-root.js +33 -0
  18. package/package/build/helpers/resolver/package.js +29 -0
  19. package/package/build/helpers/resolver.js +16 -0
  20. package/package/build/index.js +49 -0
  21. package/package/build/lib/env.js +36 -0
  22. package/package/build/lib/mkdir.js +9 -0
  23. package/package/build/lib/run.js +17 -0
  24. package/package/build/lib/spawn.js +18 -0
  25. package/package/build/tasks/browserify/compress.js +15 -0
  26. package/package/build/tasks/browserify/index.js +48 -0
  27. package/package/build/tasks/build/index.js +6 -0
  28. package/package/build/tasks/images/index.js +27 -0
  29. package/package/build/tasks/index.js +8 -0
  30. package/package/build/tasks/sass/index.js +67 -0
  31. package/package/build/tasks/translate/index.js +20 -0
  32. package/package/build/tasks/watch/index.js +161 -0
  33. package/package/components/address-lookup/default-model.js +76 -0
  34. package/package/components/address-lookup/defaults.js +25 -0
  35. package/package/components/address-lookup/index.js +251 -0
  36. package/package/components/address-lookup/templates/address-lookup.html +14 -0
  37. package/package/components/address-lookup/templates/address.html +22 -0
  38. package/package/components/address-lookup/templates/postcode.html +9 -0
  39. package/package/components/clear-session/Readme.md +46 -0
  40. package/package/components/clear-session/index.js +26 -0
  41. package/package/components/combine-and-loop-fields/Readme.md +42 -0
  42. package/package/components/combine-and-loop-fields/index.js +156 -0
  43. package/package/components/date/fields.js +16 -0
  44. package/package/components/date/index.js +172 -0
  45. package/package/components/date/templates/date.html +20 -0
  46. package/package/components/emailer/assets/images/govuk_logotype_email.png +0 -0
  47. package/package/components/emailer/assets/images/ho_crest_27px.png +0 -0
  48. package/package/components/emailer/assets/images/spacer.gif +0 -0
  49. package/package/components/emailer/email-service.js +51 -0
  50. package/package/components/emailer/emailer.js +53 -0
  51. package/package/components/emailer/index.js +74 -0
  52. package/package/components/emailer/transports/debug.js +74 -0
  53. package/package/components/emailer/transports/index.js +8 -0
  54. package/package/components/emailer/transports/ses.js +36 -0
  55. package/package/components/emailer/transports/smtp.js +26 -0
  56. package/package/components/emailer/transports/stub.js +5 -0
  57. package/package/components/emailer/views/layout.html +63 -0
  58. package/package/components/homeoffice-countries/index.js +22 -0
  59. package/package/components/index.js +13 -0
  60. package/package/components/notify/index.js +62 -0
  61. package/package/components/notify/notify.js +51 -0
  62. package/package/components/session-timeout-warning/index.js +67 -0
  63. package/package/components/summary/index.js +237 -0
  64. package/package/config/builder-defaults.js +45 -0
  65. package/package/config/component-defaults.js +13 -0
  66. package/package/config/hof-defaults.js +65 -0
  67. package/package/config/rate-limits.js +20 -0
  68. package/package/config/sanitisation-rules.js +32 -0
  69. package/package/controller/base-controller.js +296 -0
  70. package/package/controller/behaviour-hooks.js +51 -0
  71. package/package/controller/behaviour-session.js +64 -0
  72. package/package/controller/controller.js +258 -0
  73. package/package/controller/deprecate-error.js +10 -0
  74. package/package/controller/formatting/formatters.js +70 -0
  75. package/package/controller/formatting/index.js +32 -0
  76. package/package/controller/index.js +17 -0
  77. package/package/controller/validation/email.js +30 -0
  78. package/package/controller/validation/index.js +101 -0
  79. package/package/controller/validation/validators.js +181 -0
  80. package/package/controller/validation-error.js +14 -0
  81. package/package/frontend/govuk-template/build/config.js +24 -0
  82. package/package/frontend/govuk-template/build/govuk_template.html +102 -0
  83. package/package/frontend/govuk-template/build/index.js +23 -0
  84. package/package/frontend/govuk-template/govuk_template_generated.html +102 -0
  85. package/package/frontend/govuk-template/index.js +29 -0
  86. package/package/frontend/index.js +9 -0
  87. package/package/frontend/template-mixins/mixins/helpers.js +103 -0
  88. package/package/frontend/template-mixins/mixins/index.js +37 -0
  89. package/package/frontend/template-mixins/mixins/render.js +12 -0
  90. package/package/frontend/template-mixins/mixins/template-mixins.js +520 -0
  91. package/package/frontend/template-mixins/partials/forms/checkbox-group.html +47 -0
  92. package/package/frontend/template-mixins/partials/forms/checkbox.html +16 -0
  93. package/package/frontend/template-mixins/partials/forms/input-submit.html +1 -0
  94. package/package/frontend/template-mixins/partials/forms/input-text-date.html +37 -0
  95. package/package/frontend/template-mixins/partials/forms/input-text-group.html +45 -0
  96. package/package/frontend/template-mixins/partials/forms/option-group.html +43 -0
  97. package/package/frontend/template-mixins/partials/forms/select.html +17 -0
  98. package/package/frontend/template-mixins/partials/forms/textarea-group.html +37 -0
  99. package/package/frontend/template-mixins/partials/mixins/panel.html +4 -0
  100. package/package/frontend/template-partials/index.js +9 -0
  101. package/package/frontend/template-partials/translations/index.js +26 -0
  102. package/package/frontend/template-partials/translations/src/cy/base.json +4 -0
  103. package/package/frontend/template-partials/translations/src/cy/buttons.json +6 -0
  104. package/package/frontend/template-partials/translations/src/cy/cookies.json +104 -0
  105. package/package/frontend/template-partials/translations/src/cy/errorlist.json +6 -0
  106. package/package/frontend/template-partials/translations/src/cy/errors.json +18 -0
  107. package/package/frontend/template-partials/translations/src/cy/terms.json +28 -0
  108. package/package/frontend/template-partials/translations/src/en/accessibility.json +43 -0
  109. package/package/frontend/template-partials/translations/src/en/base.json +5 -0
  110. package/package/frontend/template-partials/translations/src/en/buttons.json +10 -0
  111. package/package/frontend/template-partials/translations/src/en/cookies.json +116 -0
  112. package/package/frontend/template-partials/translations/src/en/errorlist.json +7 -0
  113. package/package/frontend/template-partials/translations/src/en/errors.json +35 -0
  114. package/package/frontend/template-partials/translations/src/en/exit.json +5 -0
  115. package/package/frontend/template-partials/translations/src/en/fields.json +5 -0
  116. package/package/frontend/template-partials/translations/src/en/journey.json +6 -0
  117. package/package/frontend/template-partials/translations/src/en/save-and-exit.json +4 -0
  118. package/package/frontend/template-partials/translations/src/en/terms.json +28 -0
  119. package/package/frontend/template-partials/views/404.html +9 -0
  120. package/package/frontend/template-partials/views/accessibility.html +55 -0
  121. package/package/frontend/template-partials/views/confirm.html +8 -0
  122. package/package/frontend/template-partials/views/confirmation.html +19 -0
  123. package/package/frontend/template-partials/views/content/en/what-happens-next.md +0 -0
  124. package/package/frontend/template-partials/views/cookie-error.html +1 -0
  125. package/package/frontend/template-partials/views/cookies.html +84 -0
  126. package/package/frontend/template-partials/views/email/data-row.html +4 -0
  127. package/package/frontend/template-partials/views/email/formatted.html +12 -0
  128. package/package/frontend/template-partials/views/email/layout.html +63 -0
  129. package/package/frontend/template-partials/views/email/raw.html +11 -0
  130. package/package/frontend/template-partials/views/email/section-row.html +3 -0
  131. package/package/frontend/template-partials/views/error.html +20 -0
  132. package/package/frontend/template-partials/views/exit.html +9 -0
  133. package/package/frontend/template-partials/views/feedback-submitted.html +11 -0
  134. package/package/frontend/template-partials/views/layout.html +55 -0
  135. package/package/frontend/template-partials/views/partials/analytics-table.html +25 -0
  136. package/package/frontend/template-partials/views/partials/back.html +5 -0
  137. package/package/frontend/template-partials/views/partials/bullet-list.html +7 -0
  138. package/package/frontend/template-partials/views/partials/confirmation-alert.html +6 -0
  139. package/package/frontend/template-partials/views/partials/continue.html +5 -0
  140. package/package/frontend/template-partials/views/partials/cookie-banner.html +29 -0
  141. package/package/frontend/template-partials/views/partials/cookie-notification.html +4 -0
  142. package/package/frontend/template-partials/views/partials/cookie-settings-button.html +1 -0
  143. package/package/frontend/template-partials/views/partials/cookie-settings-radio.html +8 -0
  144. package/package/frontend/template-partials/views/partials/details-summary.html +8 -0
  145. package/package/frontend/template-partials/views/partials/external-link.html +1 -0
  146. package/package/frontend/template-partials/views/partials/form.html +10 -0
  147. package/package/frontend/template-partials/views/partials/gatag.html +60 -0
  148. package/package/frontend/template-partials/views/partials/head.html +31 -0
  149. package/package/frontend/template-partials/views/partials/heading.html +11 -0
  150. package/package/frontend/template-partials/views/partials/items-table.html +32 -0
  151. package/package/frontend/template-partials/views/partials/maincontent-left.html +10 -0
  152. package/package/frontend/template-partials/views/partials/navigation.html +8 -0
  153. package/package/frontend/template-partials/views/partials/page.html +23 -0
  154. package/package/frontend/template-partials/views/partials/panel-indent.html +3 -0
  155. package/package/frontend/template-partials/views/partials/session-cookies-table.html +28 -0
  156. package/package/frontend/template-partials/views/partials/session-timeout-warning.html +38 -0
  157. package/package/frontend/template-partials/views/partials/summary-table-row.html +14 -0
  158. package/package/frontend/template-partials/views/partials/summary-table.html +8 -0
  159. package/package/frontend/template-partials/views/partials/table.html +18 -0
  160. package/package/frontend/template-partials/views/partials/validation-list.html +3 -0
  161. package/package/frontend/template-partials/views/partials/validation-summary.html +25 -0
  162. package/package/frontend/template-partials/views/partials/warn.html +7 -0
  163. package/package/frontend/template-partials/views/rate-limit-error.html +10 -0
  164. package/package/frontend/template-partials/views/save-and-exit.html +17 -0
  165. package/package/frontend/template-partials/views/service-unavailable.html +13 -0
  166. package/package/frontend/template-partials/views/session-timeout.html +7 -0
  167. package/package/frontend/template-partials/views/step.html +14 -0
  168. package/package/frontend/template-partials/views/terms.html +26 -0
  169. package/package/frontend/themes/gov-uk/client-js/cookieSettings.js +145 -0
  170. package/package/frontend/themes/gov-uk/client-js/govuk-cookies.js +121 -0
  171. package/package/frontend/themes/gov-uk/client-js/index.js +27 -0
  172. package/package/frontend/themes/gov-uk/client-js/session-timeout-dialog.js +348 -0
  173. package/package/frontend/themes/gov-uk/client-js/skip-to-main.js +19 -0
  174. package/package/frontend/themes/gov-uk/index.js +9 -0
  175. package/package/frontend/themes/gov-uk/styles/_base.scss +17 -0
  176. package/package/frontend/themes/gov-uk/styles/_check_your_answers.scss +155 -0
  177. package/package/frontend/themes/gov-uk/styles/_cookie-banner.scss +111 -0
  178. package/package/frontend/themes/gov-uk/styles/_cookie-settings.scss +33 -0
  179. package/package/frontend/themes/gov-uk/styles/_govuk_frontend_toolkit.scss +23 -0
  180. package/package/frontend/themes/gov-uk/styles/_helpers.scss +5 -0
  181. package/package/frontend/themes/gov-uk/styles/_layout.scss +125 -0
  182. package/package/frontend/themes/gov-uk/styles/_panel-indent.scss +27 -0
  183. package/package/frontend/themes/gov-uk/styles/_pdf.scss +42 -0
  184. package/package/frontend/themes/gov-uk/styles/_session-timeout-dialog.scss +121 -0
  185. package/package/frontend/themes/gov-uk/styles/_typography.scss +27 -0
  186. package/package/frontend/themes/gov-uk/styles/_variables.scss +11 -0
  187. package/package/frontend/themes/gov-uk/styles/govuk.scss +43 -0
  188. package/package/frontend/themes/gov-uk/styles/mixins.scss +16 -0
  189. package/package/frontend/themes/gov-uk/styles/modules/_alerts.scss +73 -0
  190. package/package/frontend/themes/gov-uk/styles/modules/_buttons.scss +5 -0
  191. package/package/frontend/themes/gov-uk/styles/modules/_character-count.scss +8 -0
  192. package/package/frontend/themes/gov-uk/styles/modules/_confirm-page.scss +20 -0
  193. package/package/frontend/themes/gov-uk/styles/modules/_lists.scss +5 -0
  194. package/package/frontend/themes/gov-uk/styles/modules/_progressive-reveal.scss +17 -0
  195. package/package/frontend/themes/gov-uk/styles/modules/_validation.scss +51 -0
  196. package/package/frontend/themes/index.js +5 -0
  197. package/package/frontend/toolkit/assets/images/passports/new-window-link-blue.png +0 -0
  198. package/package/frontend/toolkit/assets/images/passports/new-window-link.png +0 -0
  199. package/package/frontend/toolkit/assets/images/spinner.gif +0 -0
  200. package/package/frontend/toolkit/assets/javascript/character-count.js +99 -0
  201. package/package/frontend/toolkit/assets/javascript/form-focus.js +101 -0
  202. package/package/frontend/toolkit/assets/javascript/helpers.js +177 -0
  203. package/package/frontend/toolkit/assets/javascript/progressive-reveal.js +72 -0
  204. package/package/frontend/toolkit/assets/javascript/validation.js +71 -0
  205. package/package/frontend/toolkit/assets/javascript/vendor/details.polyfill.js +189 -0
  206. package/package/frontend/toolkit/assets/javascript/vendor/indexof.polyfill.js +39 -0
  207. package/package/frontend/toolkit/assets/javascript/vendor/safari-cachebuster.js +6 -0
  208. package/package/frontend/toolkit/assets/stylesheets/_base.scss +17 -0
  209. package/package/frontend/toolkit/assets/stylesheets/_helpers.scss +5 -0
  210. package/package/frontend/toolkit/assets/stylesheets/_layout.scss +118 -0
  211. package/package/frontend/toolkit/assets/stylesheets/_typography.scss +27 -0
  212. package/package/frontend/toolkit/assets/stylesheets/_variables.scss +11 -0
  213. package/package/frontend/toolkit/assets/stylesheets/app.scss +30 -0
  214. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_buttons.scss +47 -0
  215. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_details.scss +38 -0
  216. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_elements-typography.scss +175 -0
  217. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_forms.scss +167 -0
  218. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_helpers.scss +39 -0
  219. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_layout.scss +67 -0
  220. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_lists.scss +40 -0
  221. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_panels.scss +29 -0
  222. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_reset.scss +33 -0
  223. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_tables.scss +33 -0
  224. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/forms/_form-block-labels.scss +63 -0
  225. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/forms/_form-date.scss +39 -0
  226. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/forms/_form-validation.scss +63 -0
  227. package/package/frontend/toolkit/assets/stylesheets/mixins.scss +16 -0
  228. package/package/frontend/toolkit/assets/stylesheets/modules/_alerts.scss +73 -0
  229. package/package/frontend/toolkit/assets/stylesheets/modules/_buttons.scss +5 -0
  230. package/package/frontend/toolkit/assets/stylesheets/modules/_confirm-page.scss +20 -0
  231. package/package/frontend/toolkit/assets/stylesheets/modules/_lists.scss +5 -0
  232. package/package/frontend/toolkit/assets/stylesheets/modules/_progressive-reveal.scss +17 -0
  233. package/package/frontend/toolkit/assets/stylesheets/modules/_validation.scss +51 -0
  234. package/package/frontend/toolkit/index.js +10 -0
  235. package/package/index.js +351 -0
  236. package/package/lib/deindex.js +18 -0
  237. package/package/lib/encryption.js +23 -0
  238. package/package/lib/ga-tag.js +89 -0
  239. package/package/lib/health.js +26 -0
  240. package/package/lib/helpers.js +66 -0
  241. package/package/lib/logger.js +65 -0
  242. package/package/lib/markdown.js +46 -0
  243. package/package/lib/router.js +111 -0
  244. package/package/lib/serve-static.js +12 -0
  245. package/package/lib/sessions.js +82 -0
  246. package/package/lib/settings.js +74 -0
  247. package/package/lib/which.js +28 -0
  248. package/package/middleware/cookies.js +43 -0
  249. package/package/middleware/deep-translate.js +32 -0
  250. package/package/middleware/errors.js +119 -0
  251. package/package/middleware/index.js +10 -0
  252. package/package/middleware/not-found.js +38 -0
  253. package/package/middleware/rate-limiter.js +98 -0
  254. package/package/middleware/service-unavailable.js +64 -0
  255. package/package/model/apis/axios-settings.js +21 -0
  256. package/package/model/apis/html-to-pdf-converter.js +35 -0
  257. package/package/model/apis/index.js +5 -0
  258. package/package/model/index.js +348 -0
  259. package/package/package.json +147 -0
  260. package/package/sandbox/README.md +66 -0
  261. package/package/sandbox/apps/sandbox/behaviours/clear-session.js +8 -0
  262. package/package/sandbox/apps/sandbox/behaviours/country-select.js +10 -0
  263. package/package/sandbox/apps/sandbox/behaviours/international-number.js +22 -0
  264. package/package/sandbox/apps/sandbox/fields.js +128 -0
  265. package/package/sandbox/apps/sandbox/index.js +99 -0
  266. package/package/sandbox/apps/sandbox/lib/staticAppealStages.js +189 -0
  267. package/package/sandbox/apps/sandbox/sections/summary-data-sections.js +43 -0
  268. package/package/sandbox/apps/sandbox/translations/src/en/errors.json +5 -0
  269. package/package/sandbox/apps/sandbox/translations/src/en/exit.json +4 -0
  270. package/package/sandbox/apps/sandbox/translations/src/en/fields.json +101 -0
  271. package/package/sandbox/apps/sandbox/translations/src/en/journey.json +7 -0
  272. package/package/sandbox/apps/sandbox/translations/src/en/pages.json +72 -0
  273. package/package/sandbox/apps/sandbox/translations/src/en/validation.json +54 -0
  274. package/package/sandbox/apps/sandbox/views/form-guidance-link.html +8 -0
  275. package/package/sandbox/apps/sandbox/views/save-and-exit.html +19 -0
  276. package/package/sandbox/assets/images/icons/icon-caret-left.png +0 -0
  277. package/package/sandbox/assets/images/icons/icon-complete.png +0 -0
  278. package/package/sandbox/assets/images/icons/icon-cross-remove-sign.png +0 -0
  279. package/package/sandbox/assets/js/index.js +70 -0
  280. package/package/sandbox/assets/scss/app.scss +27 -0
  281. package/package/sandbox/codecept.conf.js +15 -0
  282. package/package/sandbox/config.js +17 -0
  283. package/package/sandbox/package.json +26 -0
  284. package/package/sandbox/server.js +23 -0
  285. package/package/sandbox/yarn.lock +262 -0
  286. package/package/transpiler/index.js +2 -0
  287. package/package/transpiler/lib/aggregate.js +32 -0
  288. package/package/transpiler/lib/build.js +15 -0
  289. package/package/transpiler/lib/compile.js +12 -0
  290. package/package/transpiler/lib/expand-dirs.js +14 -0
  291. package/package/transpiler/lib/write-files.js +24 -0
  292. package/package/utilities/autofill/index.js +189 -0
  293. package/package/utilities/autofill/inputs.js +60 -0
  294. package/package/utilities/countries.js +12 -0
  295. package/package/utilities/helpers/index.js +189 -0
  296. package/package/utilities/index.js +9 -0
  297. package/package/utilities/reqres/index.js +18 -0
  298. package/package/utilities/test-data/data/domain.json +7 -0
  299. package/package/utilities/test-data/data/firstname.json +16 -0
  300. package/package/utilities/test-data/data/lastname.json +10 -0
  301. package/package/utilities/test-data/data/postcode.json +12 -0
  302. package/package/utilities/test-data/data/streetname.json +8 -0
  303. package/package/utilities/test-data/data/streetsuffix.json +7 -0
  304. package/package/utilities/test-data/data/town.json +9 -0
  305. package/package/utilities/test-data/index.js +67 -0
  306. package/package/wizard/behaviours/complete.js +20 -0
  307. package/package/wizard/behaviours/index.js +5 -0
  308. package/package/wizard/index.js +124 -0
  309. package/package/wizard/middleware/back-links.js +68 -0
  310. package/package/wizard/middleware/check-complete.js +13 -0
  311. package/package/wizard/middleware/check-progress.js +139 -0
  312. package/package/wizard/middleware/check-session.js +17 -0
  313. package/package/wizard/middleware/csrf.js +47 -0
  314. package/package/wizard/middleware/session-model.js +11 -0
  315. package/package/wizard/middleware/session.js +9 -0
  316. package/package/wizard/model.js +29 -0
  317. package/package/wizard/util/constants.js +5 -0
  318. package/package/wizard/util/helpers.js +19 -0
  319. package/package.json +5 -6
  320. package/.editorconfig +0 -10
  321. package/.github/workflows/automate-publish.yml +0 -38
  322. package/.github/workflows/automate-tag.yml +0 -78
  323. package/.istanbul.yml +0 -20
  324. package/codeReviewChecklist.md +0 -22
  325. package/pull_request_template.md +0 -16
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+ const debug = require('debug')('hof:progress-check');
5
+ const helpers = require('../util/helpers');
6
+
7
+ module.exports = (route, controller, steps, begin) => {
8
+ const start = begin || '/';
9
+ const previousSteps = helpers.getRouteSteps(route, steps);
10
+ const prereqs = (controller.options.prereqs || []).concat(previousSteps);
11
+
12
+ const invalidatingFields = _.pickBy(controller.options.fields, function (field) {
13
+ return field && field.invalidates && field.invalidates.length;
14
+ });
15
+
16
+ const getAllPossibleSteps = (stepName, scopedSteps, stps) => {
17
+ let allSteps = stps || [stepName];
18
+ let step = scopedSteps[stepName];
19
+ const forksReducer = (arr, fork) => getAllPossibleSteps(fork, scopedSteps, allSteps);
20
+ // don't loop over steps that have already been added
21
+ while (step && step.next && allSteps.indexOf(step.next) === -1) {
22
+ allSteps.push(step.next);
23
+ // ignore forks that have already been traversed.
24
+ const forks = _.difference(_.map(step.forks, 'target'), allSteps);
25
+ allSteps = allSteps.concat(forks.reduce(forksReducer, []));
26
+ step = scopedSteps[step.next];
27
+ }
28
+ return _.uniq(allSteps);
29
+ };
30
+
31
+ // Gets all the possible routes
32
+ const walkAllPossibleSteps = (stepName, allStepsInService, allVisitedSteps) => {
33
+ const stepIncludingFieldsAndForks = allStepsInService[stepName];
34
+ if (!stepIncludingFieldsAndForks) { return; }
35
+
36
+ const forkTargets = _.map(stepIncludingFieldsAndForks.forks, 'target') || [];
37
+ const nextStep = stepIncludingFieldsAndForks.next || '';
38
+
39
+ // If there is no next step or fork, then we have reached the end of the journey
40
+ if (!forkTargets.length && !nextStep) {
41
+ allVisitedSteps.push(stepName);
42
+ // eslint-disable-next-line consistent-return
43
+ return _.uniq(allVisitedSteps);
44
+ }
45
+
46
+ const nextStepsAndForks = _.uniq(forkTargets.concat(nextStep));
47
+
48
+ // We need to transverse through all 'Next' and 'Forks' for this route
49
+ nextStepsAndForks.map(each => {
50
+ if (!allVisitedSteps.includes(each)) {
51
+ allVisitedSteps.push(each);
52
+ walkAllPossibleSteps(each, allStepsInService, allVisitedSteps);
53
+ }
54
+ });
55
+ };
56
+
57
+ // Create a list of all visited steps
58
+ const createAllVisitedSteps = (stepName, allStepsInService) => {
59
+ const allVisitedSteps = [stepName];
60
+ if (allStepsInService[stepName]) {
61
+ walkAllPossibleSteps(stepName, allStepsInService, allVisitedSteps);
62
+ }
63
+ return _.uniq(allVisitedSteps);
64
+ };
65
+
66
+ const invalidateStep = (stepName, scopedSteps, sessionModel) => {
67
+ debug('Invalidating', stepName);
68
+ const step = scopedSteps[stepName] || {};
69
+ sessionModel.unset(step.fields || []);
70
+ sessionModel.set('steps', _.without(sessionModel.get('steps'), stepName));
71
+ };
72
+
73
+ // detect if a path will arrive back at the current step if followed
74
+ const isLoop = (target, current) => {
75
+ debug('target', target);
76
+ debug('current', current);
77
+ debug('paths', getAllPossibleSteps(target, steps));
78
+ return getAllPossibleSteps(target, steps).indexOf(current) > -1;
79
+ };
80
+
81
+ const invalidatePath = (req, res) => {
82
+ const nextStep = controller.getForkTarget(req, res);
83
+
84
+ const forks = controller.options.forks.map(fork => fork.target);
85
+
86
+ let potentialPaths = [controller.options.next].concat(forks);
87
+ debug('potential paths', potentialPaths);
88
+ // do not invalidate forks which loop back to the current step and are *not* being followed
89
+ potentialPaths = potentialPaths.filter(path => path === nextStep || !isLoop(path, route));
90
+ debug('next', nextStep);
91
+ debug('potential paths', potentialPaths);
92
+ // if we're following a loop then allow the loop to be invalidated
93
+ const whitelist = isLoop(nextStep, req.path) ? [route] : createAllVisitedSteps(nextStep, steps);
94
+ // aggregate all potential journeys from the invalidating step
95
+ const invalidateSteps = potentialPaths.reduce((arr, step) => arr.concat(getAllPossibleSteps(step, steps)), []);
96
+
97
+ _.difference(_.uniq(invalidateSteps), whitelist).forEach(step => {
98
+ invalidateStep(step, steps, req.sessionModel);
99
+ });
100
+ };
101
+
102
+ controller.on('complete', (req, res, p) => {
103
+ const sessionsteps = req.sessionModel.get('steps') || [];
104
+ const path = p || route;
105
+ debug('Marking path complete ', path);
106
+ const index = sessionsteps.indexOf(path);
107
+ if (index > -1) {
108
+ sessionsteps.splice(index, 1);
109
+ }
110
+ sessionsteps.push(path);
111
+ req.sessionModel.set('steps', sessionsteps);
112
+
113
+ if (req.method === 'POST' && controller.options.forks) {
114
+ invalidatePath(req, res);
115
+ }
116
+ });
117
+
118
+ return (req, res, next) => {
119
+ _.each(invalidatingFields, (field, key) => {
120
+ req.sessionModel.on('change:' + key, () => {
121
+ debug('Unsetting fields %s', field.invalidates.join(', '));
122
+ req.sessionModel.unset(field.invalidates);
123
+ });
124
+ });
125
+
126
+ const visited = _.intersection(req.sessionModel.get('steps'), prereqs);
127
+
128
+ debug('Steps ', req.sessionModel.get('steps'));
129
+ debug('Prereqs ' + prereqs);
130
+ debug('Visited ' + visited);
131
+ if (visited.length || !prereqs.length || route === start) {
132
+ next();
133
+ } else {
134
+ const err = new Error('Attempt to access page without prerequisite steps being completed');
135
+ err.code = 'MISSING_PREREQ';
136
+ next(err);
137
+ }
138
+ };
139
+ };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const secureHttps = config => config.protocol === 'https' || config.env === 'production';
4
+
5
+ module.exports = (route, controller, steps, first, settings) => (req, res, next) => {
6
+ if (controller.options.checkSession !== false && (req.method === 'POST' || req.path !== first)) {
7
+ if (req.cookies['hof-wizard-sc'] && req.session.exists !== true) {
8
+ const err = new Error('Session expired');
9
+ err.code = 'SESSION_TIMEOUT';
10
+ return next(err);
11
+ }
12
+ }
13
+ req.session.exists = true;
14
+ // Set samesite to lax to allow setting cookies on redirects from Gov.UK
15
+ res.cookie('hof-wizard-sc', 1, { sameSite: 'lax', secure: secureHttps(settings), httpOnly: true });
16
+ return next();
17
+ };
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ const csrf = require('csrf')();
4
+
5
+ module.exports = (route, controller) => {
6
+ if (controller.options.csrf !== false) {
7
+ return (req, res, next) => {
8
+ const verify = () => {
9
+ const secret = req.sessionModel.get('csrf-secret');
10
+ const safeMethods = ['GET', 'HEAD', 'OPTIONS'];
11
+
12
+ if (!secret) {
13
+ csrf.secret((err, sec) => {
14
+ if (err) {
15
+ next(err);
16
+ }
17
+ req.sessionModel.set('csrf-secret', sec);
18
+ verify();
19
+ });
20
+ } else if (safeMethods.indexOf(req.method) > -1) {
21
+ // The HTTP method is safe. No need to verify a
22
+ // token. Instead, provide a new one for future
23
+ // verification.
24
+ res.locals['csrf-token'] = csrf.create(secret);
25
+ next();
26
+ } else {
27
+ // The HTTP method is assumed to be unsafe so
28
+ // require verification.
29
+
30
+ // Token can be provided in either the request body
31
+ // or the headers. Preference is given to the body.
32
+ const token = req.body['x-csrf-token']
33
+ || req.headers['x-csrf-token'];
34
+
35
+ if (!csrf.verify(secret, token)) {
36
+ next({ code: 'CSRF_ERROR' });
37
+ } else {
38
+ next();
39
+ }
40
+ }
41
+ };
42
+
43
+ verify();
44
+ };
45
+ }
46
+ return (req, res, next) => next();
47
+ };
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ const Model = require('../model');
4
+
5
+ module.exports = options => (req, res, next) => {
6
+ req.sessionModel = new Model({}, {
7
+ session: req.session,
8
+ key: options.name
9
+ });
10
+ next();
11
+ };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ module.exports = (req, res, next) => {
4
+ if (typeof req.session === 'undefined') {
5
+ throw new Error('Session is undefined');
6
+ } else {
7
+ next();
8
+ }
9
+ };
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const Model = require('../model');
4
+
5
+ module.exports = class SessionModel extends Model {
6
+ constructor(props, options) {
7
+ const session = options.session;
8
+ const key = options.key;
9
+
10
+ if (!key || typeof key !== 'string') {
11
+ throw new Error('session-model - key must be defined');
12
+ }
13
+
14
+ session[key] = session[key] || {};
15
+
16
+ // include session values on initialized attributes
17
+ const attrs = Object.assign({}, session[key], props);
18
+
19
+ super(attrs, options);
20
+
21
+ // write changes back to the session
22
+ this.on('change', changes => {
23
+ Object.assign(session[key], changes);
24
+ });
25
+ this.on('reset', () => {
26
+ session[key] = {};
27
+ });
28
+ }
29
+ };
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ APPLICATION_COMPLETE: '__application_complete'
5
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+
5
+ module.exports = {
6
+ getRouteSteps(route, steps) {
7
+ return _.reduce(steps, (list, step, path) => {
8
+ const isNext = step.next === route;
9
+ const targets = _.map((step.forks || []), 'target');
10
+
11
+ const isFork = targets.some(fork => fork === route);
12
+
13
+ if (isNext || isFork) {
14
+ list.push(path);
15
+ }
16
+ return list;
17
+ }, []);
18
+ }
19
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hof",
3
3
  "description": "A bootstrap for HOF projects",
4
- "version": "22.8.4",
4
+ "version": "22.9.0-beta.v1",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
7
7
  "author": "HomeOffice",
@@ -82,14 +82,14 @@
82
82
  "nodemailer": "^6.6.3",
83
83
  "nodemailer-ses-transport": "^1.5.1",
84
84
  "nodemailer-stub-transport": "^1.1.0",
85
- "notifications-node-client": "^8.2.0",
85
+ "notifications-node-client": "^8.2.1",
86
86
  "redis": "^3.1.2",
87
87
  "reqres": "^3.0.1",
88
88
  "rimraf": "^3.0.2",
89
89
  "sass": "^1.56.2",
90
90
  "serve-static": "^1.14.1",
91
91
  "uglify-js": "^3.14.3",
92
- "underscore": "^1.13.6",
92
+ "underscore": "^1.13.7",
93
93
  "urijs": "^1.19.11",
94
94
  "uuid": "^8.3.2",
95
95
  "winston": "^3.7.2"
@@ -104,8 +104,8 @@
104
104
  "chai-subset": "^1.6.0",
105
105
  "concat-stream": "^1.4.7",
106
106
  "csv": "^5.3.2",
107
- "eslint": "^7.30.0",
108
- "eslint-config-hof": "^1.1.0",
107
+ "eslint": "^8.57.0",
108
+ "eslint-config-hof": "^1.3.4",
109
109
  "funkie": "0.0.5",
110
110
  "funkie-phantom": "0.0.1",
111
111
  "istanbul": "^0.4.3",
@@ -141,7 +141,6 @@
141
141
  "exit": "true"
142
142
  },
143
143
  "resolutions": {
144
- "underscore": "^1.12.1",
145
144
  "cached-path-relative": "^1.1.0",
146
145
  "shell-quote": "^1.7.3"
147
146
  }
package/.editorconfig DELETED
@@ -1,10 +0,0 @@
1
- # EditorConfig is awesome: http://EditorConfig.org
2
- root = true
3
-
4
- # Unix-style newlines with a newline ending every file
5
- [*]
6
- end_of_line = lf
7
- insert_final_newline = true
8
- charset = utf-8
9
- indent_style = space
10
- indent_size = 2
@@ -1,38 +0,0 @@
1
- # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
- # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
3
- name: Automate_Publish
4
- on:
5
- workflow_run:
6
- workflows: ["Automate_Tag"]
7
- types:
8
- - completed
9
- jobs:
10
- auto-publish:
11
- runs-on: ubuntu-22.04
12
- if: startsWith(github.ref, 'refs/heads/master')
13
- steps:
14
- - uses: actions/checkout@v4
15
- with:
16
- fetch-depth: 0
17
- - uses: actions/setup-node@v4
18
- with:
19
- node-version: 20
20
- registry-url: https://registry.npmjs.org/
21
- - name: 'Get Previous tag'
22
- id: previoustag
23
- uses: "WyriHaximus/github-action-get-previous-tag@v1"
24
- - uses: borales/actions-yarn@v3.0.0
25
- with:
26
- cmd: install --frozen-lockfile
27
- - run: |
28
- npm_tag="v$(npm dist-tags | cut -d' ' -f 2)"
29
- git_tag="$(git describe --tags | cut -d'-' -f 1)"
30
- if [ "$npm_tag" != "$git_tag" ] ; then npm publish; fi
31
- env:
32
- NODE_AUTH_TOKEN: ${{ secrets.npm_bot_token }}
33
- - name: 'Publish Release'
34
- uses: Roang-zero1/github-create-release-action@master
35
- with:
36
- created_tag: ${{ steps.previoustag.outputs.tag }}
37
- env:
38
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -1,78 +0,0 @@
1
- # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
- # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
3
- name: Automate_Tag
4
- on: [push]
5
- jobs:
6
- test:
7
- runs-on: ubuntu-22.04
8
- strategy:
9
- matrix:
10
- node-version: [20.x]
11
- redis-version: [4, 5, 6]
12
- steps:
13
- - uses: actions/checkout@v4
14
- - uses: actions/setup-node@v4
15
- with:
16
- node-version: ${{ matrix.node-version }}
17
- - name: Start Redis
18
- uses: supercharge/redis-github-action@1.2.0
19
- with:
20
- redis-version: ${{ matrix.redis-version }}
21
- - uses: borales/actions-yarn@v3.0.0
22
- with:
23
- cmd: install --frozen-lockfile
24
- - run: npm test
25
-
26
- auto-tag-patch:
27
- needs: test
28
- runs-on: ubuntu-22.04
29
- if: |
30
- startsWith(github.ref, 'refs/heads/master') &&
31
- !contains(github.event.head_commit.message, '[MAJOR]') &&
32
- !contains(github.event.head_commit.message, '[MINOR]')
33
- steps:
34
- - uses: actions/checkout@v4
35
- - uses: actions/setup-node@v4
36
- with:
37
- node-version: 20
38
- registry-url: https://registry.npmjs.org/
39
- - run: |
40
- git config --local user.email "$(git log --format='%ae' HEAD^!)"
41
- git config --local user.name "$(git log --format='%an' HEAD^!)"
42
- npm version patch
43
-
44
- auto-tag-minor:
45
- needs: test
46
- runs-on: ubuntu-22.04
47
- if: |
48
- startsWith(github.ref, 'refs/heads/master') &&
49
- !contains(github.event.head_commit.message, '[MAJOR]') &&
50
- contains(github.event.head_commit.message, '[MINOR]')
51
- steps:
52
- - uses: actions/checkout@v4
53
- - uses: actions/setup-node@v4
54
- with:
55
- node-version: 20
56
- registry-url: https://registry.npmjs.org/
57
- - run: |
58
- git config --local user.email "$(git log --format='%ae' HEAD^!)"
59
- git config --local user.name "$(git log --format='%an' HEAD^!)"
60
- npm version minor
61
-
62
- auto-tag-major:
63
- needs: test
64
- runs-on: ubuntu-22.04
65
- if: |
66
- startsWith(github.ref, 'refs/heads/master') &&
67
- contains(github.event.head_commit.message, '[MAJOR]') &&
68
- !contains(github.event.head_commit.message, '[MINOR]')
69
- steps:
70
- - uses: actions/checkout@v4
71
- - uses: actions/setup-node@v4
72
- with:
73
- node-version: 20
74
- registry-url: https://registry.npmjs.org/
75
- - run: |
76
- git config --local user.email "$(git log --format='%ae' HEAD^!)"
77
- git config --local user.name "$(git log --format='%an' HEAD^!)"
78
- npm version major
package/.istanbul.yml DELETED
@@ -1,20 +0,0 @@
1
- instrumentation:
2
- root: .
3
- extensions:
4
- - .js
5
- default-excludes: true
6
- include-all-sources: true
7
- check:
8
- global:
9
- statements: 80
10
- lines: 80
11
- branches: 80
12
- functions: 80
13
- reporting:
14
- print: summary
15
- reports:
16
- - html
17
- dir: ./coverage
18
- report-config:
19
- html:
20
- dir: coverage
@@ -1,22 +0,0 @@
1
- # HOF code review checklist v1.0
2
-
3
- This is a general guide on what you should check for when reviewing another team member's code.
4
-
5
- ## Fundamental checks
6
- - [ ] Check for code format
7
- - [ ] Check for duplicate code
8
- - [ ] Check for if there are existing components in the framework already
9
- - [ ] Check for copy and paste
10
- - [ ] Check code readability (if the class, function and variable names are making sense, avoid using acronyms, check for simplicity, avoid complexity)
11
- - [ ] Check if user inputs are sanitized
12
- - [ ] Check if errors are handled
13
- - [ ] Check if null / undefined values are checked before actions are performed on a variable (May not always be necessary)
14
- - [ ] Check for performance (are there logic in loops that doesn't have to be executed each time? Could some tasks be added to a queue and performed later? etc)
15
-
16
- ## Advanced (optional if the ticket is low / medium impact) checks
17
- - [ ] Check if the code is following SOLID principle, code maintainability
18
- - [ ] Check if none functional requirements are needed (for example, should an audit log be stored for an action performed)
19
- - [ ] Check the performance and efficiency of the tests
20
- - [ ] Check to avoid the use of operations that only work in javascript (e.g. using && to return the object on the right if the statement on the left is true)
21
-
22
-
@@ -1,16 +0,0 @@
1
- ## What?
2
- ## Why?
3
- ## How?
4
- ## Testing?
5
- ## Screenshots (optional)
6
- ## Anything Else? (optional)
7
- ## Check list
8
-
9
- - [ ] I have reviewed my own pull request for linting issues (e.g. adding new lines)
10
- - [ ] I have written tests (if relevant)
11
- - [ ] I have created a JIRA number for my branch
12
- - [ ] I have created a JIRA number for my commit
13
- - [ ] I have followed the chris beams method for my commit https://cbea.ms/git-commit/
14
- here is an [example commit](https://github.com/UKHomeOfficeForms/hof/commit/810959f391187c7c4af6db262bcd143b50093a6e)
15
- - [ ] Ensure workflow jobs are passing especially tests
16
- - [ ] I will squash the commits before merging