@dwp/govuk-casa 9.3.3 → 9.3.4
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.
- package/dist/assets/css/casa.css +1 -1
- package/dist/assets/css/casa.css.map +1 -1
- package/dist/lib/CasaTemplateLoader.js +22 -28
- package/dist/lib/CasaTemplateLoader.js.map +1 -1
- package/dist/lib/JourneyContext.js +86 -112
- package/dist/lib/JourneyContext.js.map +1 -1
- package/dist/lib/MutableRouter.js +71 -80
- package/dist/lib/MutableRouter.js.map +1 -1
- package/dist/lib/Plan.js +15 -26
- package/dist/lib/Plan.js.map +1 -1
- package/dist/lib/ValidationError.js +3 -3
- package/dist/lib/ValidationError.js.map +1 -1
- package/dist/lib/configuration-ingestor.js +21 -10
- package/dist/lib/configuration-ingestor.js.map +1 -1
- package/dist/lib/configure.js +18 -17
- package/dist/lib/configure.js.map +1 -1
- package/dist/lib/end-session.js +5 -5
- package/dist/lib/end-session.js.map +1 -1
- package/dist/lib/field.js +56 -65
- package/dist/lib/field.js.map +1 -1
- package/dist/lib/nunjucks-filters.js +6 -6
- package/dist/lib/nunjucks-filters.js.map +1 -1
- package/dist/lib/nunjucks.js +3 -3
- package/dist/lib/nunjucks.js.map +1 -1
- package/dist/lib/utils.js +6 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/validators/dateObject.js +23 -14
- package/dist/lib/validators/dateObject.js.map +1 -1
- package/dist/lib/validators/email.js +2 -5
- package/dist/lib/validators/email.js.map +1 -1
- package/dist/lib/validators/inArray.js +2 -5
- package/dist/lib/validators/inArray.js.map +1 -1
- package/dist/lib/validators/nino.js +1 -4
- package/dist/lib/validators/nino.js.map +1 -1
- package/dist/lib/validators/postalAddressObject.js +26 -19
- package/dist/lib/validators/postalAddressObject.js.map +1 -1
- package/dist/lib/validators/range.js +2 -6
- package/dist/lib/validators/range.js.map +1 -1
- package/dist/lib/validators/regex.js +1 -4
- package/dist/lib/validators/regex.js.map +1 -1
- package/dist/lib/validators/required.js +1 -4
- package/dist/lib/validators/required.js.map +1 -1
- package/dist/lib/validators/strlen.js +1 -4
- package/dist/lib/validators/strlen.js.map +1 -1
- package/dist/lib/validators/wordCount.js +1 -4
- package/dist/lib/validators/wordCount.js.map +1 -1
- package/dist/middleware/csrf.js +4 -2
- package/dist/middleware/csrf.js.map +1 -1
- package/dist/middleware/data.js +17 -10
- package/dist/middleware/data.js.map +1 -1
- package/dist/middleware/i18n.d.ts +1 -1
- package/dist/middleware/i18n.js +16 -16
- package/dist/middleware/i18n.js.map +1 -1
- package/dist/middleware/post.js +9 -7
- package/dist/middleware/post.js.map +1 -1
- package/dist/middleware/pre.js +2 -2
- package/dist/middleware/pre.js.map +1 -1
- package/dist/middleware/sanitise-fields.d.ts +1 -1
- package/dist/middleware/sanitise-fields.js +1 -2
- package/dist/middleware/sanitise-fields.js.map +1 -1
- package/dist/middleware/session.js +11 -6
- package/dist/middleware/session.js.map +1 -1
- package/dist/middleware/strip-proxy-path.js +1 -2
- package/dist/middleware/strip-proxy-path.js.map +1 -1
- package/dist/middleware/validate-fields.d.ts +1 -1
- package/dist/middleware/validate-fields.js +1 -2
- package/dist/middleware/validate-fields.js.map +1 -1
- package/dist/routes/journey.js +15 -11
- package/dist/routes/journey.js.map +1 -1
- package/dist/routes/static.js +8 -9
- package/dist/routes/static.js.map +1 -1
- package/package.json +23 -22
- package/src/lib/JourneyContext.js +22 -19
- package/src/lib/MutableRouter.js +2 -2
- package/src/lib/Plan.js +2 -8
- package/src/lib/ValidationError.js +2 -2
- package/src/lib/configuration-ingestor.js +21 -12
- package/src/lib/configure.js +14 -11
- package/src/lib/end-session.js +5 -5
- package/src/lib/nunjucks-filters.js +6 -6
- package/src/lib/nunjucks.js +2 -2
- package/src/lib/validators/dateObject.js +5 -5
- package/src/lib/validators/postalAddressObject.js +8 -10
- package/src/middleware/data.js +4 -7
- package/src/middleware/i18n.js +9 -9
- package/src/middleware/pre.js +1 -1
- package/src/middleware/sanitise-fields.js +1 -2
- package/src/routes/journey.js +2 -2
- package/src/routes/static.js +4 -4
package/dist/routes/static.js
CHANGED
|
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.default = staticRouter;
|
|
7
7
|
const express_1 = __importDefault(require("express"));
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_url_1 = require("node:url");
|
|
10
|
+
const node_path_1 = require("node:path");
|
|
11
|
+
const node_module_1 = require("node:module");
|
|
12
12
|
const dirname_cjs_1 = __importDefault(require("./dirname.cjs"));
|
|
13
13
|
const MutableRouter_js_1 = __importDefault(require("../lib/MutableRouter.js"));
|
|
14
14
|
const utils_js_1 = require("../lib/utils.js");
|
|
@@ -33,11 +33,10 @@ function staticRouter({ maxAge = 3600000 } = {}) {
|
|
|
33
33
|
next(new Error("404"));
|
|
34
34
|
};
|
|
35
35
|
const setHeaders = (req, res, next) => {
|
|
36
|
-
var _a;
|
|
37
36
|
res.set("cache-control", "public");
|
|
38
37
|
res.set("pragma", "cache");
|
|
39
38
|
res.set("expires", new Date(Date.now() + oneDay).toUTCString());
|
|
40
|
-
const { pathname } = new
|
|
39
|
+
const { pathname } = new node_url_1.URL(req?.originalUrl ?? "", "https://placeholder.test/");
|
|
41
40
|
if (pathname.substr(-4) === ".css") {
|
|
42
41
|
// Just needed for our in-memory CSS assets
|
|
43
42
|
res.set("content-type", "text/css");
|
|
@@ -56,17 +55,17 @@ function staticRouter({ maxAge = 3600000 } = {}) {
|
|
|
56
55
|
// must be replaced with the dynamic `mountUrl` to ensure govuk-frontend
|
|
57
56
|
// assets are served from the correct location.
|
|
58
57
|
/* eslint-disable security/detect-non-literal-fs-filename */
|
|
59
|
-
const casaCss = (0,
|
|
58
|
+
const casaCss = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(dirname_cjs_1.default, "../../dist/assets/css/casa.css"), { encoding: "utf8" });
|
|
60
59
|
/* eslint-enable security/detect-non-literal-fs-filename */
|
|
61
60
|
// The static middleware will only server GET/HEAD requests, so we can mount
|
|
62
61
|
// the middleware using `use()` rather than resorting to `get()`
|
|
63
|
-
const govukFrontendDirectory = (0,
|
|
62
|
+
const govukFrontendDirectory = (0, node_path_1.resolve)((0, node_module_1.createRequire)(dirname_cjs_1.default).resolve("govuk-frontend"), "../../");
|
|
64
63
|
router.use("/govuk/govuk-frontend.min.js", ExpressStatic(`${govukFrontendDirectory}/govuk/govuk-frontend.min.js`, staticConfig));
|
|
65
64
|
router.use("/govuk/govuk-frontend.min.js.map", ExpressStatic(`${govukFrontendDirectory}/govuk/govuk-frontend.min.js.map`, staticConfig));
|
|
66
65
|
router.use("/govuk/assets", ExpressStatic(`${govukFrontendDirectory}/govuk/assets`, staticConfig));
|
|
67
66
|
router.use("/govuk/assets", notFoundHandler);
|
|
68
67
|
router.get("/casa/assets/css/casa.css", setHeaders, (req, res) => res.send(casaCss.replace(/~~~CASA_MOUNT_URL~~~/g, (0, utils_js_1.validateUrlPath)(`${req.baseUrl}/`))));
|
|
69
|
-
router.use("/casa/assets/css/casa.css.map", ExpressStatic((0,
|
|
68
|
+
router.use("/casa/assets/css/casa.css.map", ExpressStatic((0, node_path_1.resolve)(dirname_cjs_1.default, "../../dist/assets/css/casa.css.map")));
|
|
70
69
|
router.use("/casa/assets", notFoundHandler);
|
|
71
70
|
return router;
|
|
72
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/routes/static.js"],"names":[],"mappings":";;;;;AA2BA,+BAoFC;AA/GD,sDAAgC;AAChC,
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/routes/static.js"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dwp/govuk-casa",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.4",
|
|
4
4
|
"description": "A framework for building GOVUK Collect-And-Submit-Applications",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -56,49 +56,50 @@
|
|
|
56
56
|
"deepmerge": "4.3.1",
|
|
57
57
|
"express": "4.21.1",
|
|
58
58
|
"express-session": "1.18.1",
|
|
59
|
-
"govuk-frontend": "5.7.
|
|
60
|
-
"helmet": "7.
|
|
61
|
-
"i18next": "23.
|
|
59
|
+
"govuk-frontend": "5.7.1",
|
|
60
|
+
"helmet": "7.2.0",
|
|
61
|
+
"i18next": "23.16.4",
|
|
62
62
|
"i18next-http-middleware": "3.6.0",
|
|
63
63
|
"js-yaml": "4.1.0",
|
|
64
64
|
"lodash": "4.17.21",
|
|
65
65
|
"luxon": "3.5.0",
|
|
66
66
|
"nunjucks": "3.2.4",
|
|
67
67
|
"path-to-regexp": "8.2.0",
|
|
68
|
+
"rfdc": "1.4.1",
|
|
68
69
|
"validator": "13.12.0"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
|
71
|
-
"@babel/core": "7.
|
|
72
|
-
"@babel/eslint-parser": "7.25.
|
|
73
|
-
"@babel/preset-env": "7.
|
|
72
|
+
"@babel/core": "7.26.0",
|
|
73
|
+
"@babel/eslint-parser": "7.25.9",
|
|
74
|
+
"@babel/preset-env": "7.26.0",
|
|
74
75
|
"@ckeditor/jsdoc-plugins": "42.1.0",
|
|
75
|
-
"@commitlint/config-conventional": "19.
|
|
76
|
-
"@dwp/casa-spiderplan": "4.0.
|
|
77
|
-
"@dwp/casa-spiderplan-a11y-plugin": "1.0.
|
|
76
|
+
"@commitlint/config-conventional": "19.5.0",
|
|
77
|
+
"@dwp/casa-spiderplan": "4.0.2",
|
|
78
|
+
"@dwp/casa-spiderplan-a11y-plugin": "1.0.1",
|
|
78
79
|
"@dwp/casa-spiderplan-zap-plugin": "1.0.0",
|
|
79
80
|
"@dwp/eslint-config-base": "7.0.0",
|
|
80
81
|
"@types/express": "4.17.21",
|
|
81
|
-
"@types/node": "22.
|
|
82
|
+
"@types/node": "22.8.6",
|
|
82
83
|
"@types/nunjucks": "3.2.6",
|
|
83
84
|
"c8": "10.1.2",
|
|
84
|
-
"chai": "5.1.
|
|
85
|
+
"chai": "5.1.2",
|
|
85
86
|
"cheerio": "1.0.0",
|
|
86
|
-
"commitlint": "19.
|
|
87
|
+
"commitlint": "19.5.0",
|
|
87
88
|
"docdash": "2.0.2",
|
|
88
|
-
"eslint": "8.57.
|
|
89
|
-
"eslint-plugin-import": "2.
|
|
90
|
-
"eslint-plugin-jsdoc": "48.
|
|
89
|
+
"eslint": "8.57.1",
|
|
90
|
+
"eslint-plugin-import": "2.31.0",
|
|
91
|
+
"eslint-plugin-jsdoc": "48.11.0",
|
|
91
92
|
"eslint-plugin-security": "2.1.1",
|
|
92
93
|
"eslint-plugin-sonarjs": "0.25.1",
|
|
93
|
-
"fast-check": "3.
|
|
94
|
-
"jsdoc": "4.0.
|
|
94
|
+
"fast-check": "3.23.0",
|
|
95
|
+
"jsdoc": "4.0.4",
|
|
95
96
|
"jsdoc-tsimport-plugin": "1.0.5",
|
|
96
|
-
"mocha": "10.
|
|
97
|
+
"mocha": "10.8.2",
|
|
97
98
|
"prettier": "3.3.3",
|
|
98
99
|
"prettier-plugin-jsdoc": "1.3.0",
|
|
99
|
-
"sass": "1.
|
|
100
|
-
"sinon": "18.0.
|
|
100
|
+
"sass": "1.80.6",
|
|
101
|
+
"sinon": "18.0.1",
|
|
101
102
|
"supertest": "7.0.0",
|
|
102
|
-
"typescript": "5.
|
|
103
|
+
"typescript": "5.6.3"
|
|
103
104
|
}
|
|
104
105
|
}
|
|
@@ -7,17 +7,20 @@
|
|
|
7
7
|
* - Navigation information about how the user got where they are.
|
|
8
8
|
*/
|
|
9
9
|
import lodash from "lodash";
|
|
10
|
+
import rfdc from "rfdc";
|
|
10
11
|
import ValidationError from "./ValidationError.js";
|
|
11
12
|
import logger from "./logger.js";
|
|
12
13
|
import { notProto } from "./utils.js";
|
|
13
14
|
import { uuid as uuidGenerator } from "./context-id-generators.js";
|
|
14
15
|
|
|
15
|
-
const { isPlainObject, isObject,
|
|
16
|
+
const { isPlainObject, isObject, isEqual } = lodash; // CommonJS
|
|
16
17
|
|
|
17
18
|
const log = logger("lib:journey-context");
|
|
18
19
|
|
|
19
20
|
const uuid = uuidGenerator();
|
|
20
21
|
|
|
22
|
+
const clone = rfdc({ proto: false });
|
|
23
|
+
|
|
21
24
|
/**
|
|
22
25
|
* @typedef {import("../casa").ContextEventUserInfo} ContextEventUserInfo
|
|
23
26
|
* @access private
|
|
@@ -123,10 +126,10 @@ export default class JourneyContext {
|
|
|
123
126
|
*/
|
|
124
127
|
toObject() {
|
|
125
128
|
return Object.assign(Object.create(null), {
|
|
126
|
-
data:
|
|
127
|
-
validation:
|
|
128
|
-
nav:
|
|
129
|
-
identity:
|
|
129
|
+
data: clone(this.#data),
|
|
130
|
+
validation: clone(this.#validation),
|
|
131
|
+
nav: clone(this.#nav),
|
|
132
|
+
identity: clone(this.#identity),
|
|
130
133
|
});
|
|
131
134
|
}
|
|
132
135
|
|
|
@@ -294,11 +297,11 @@ export default class JourneyContext {
|
|
|
294
297
|
);
|
|
295
298
|
}
|
|
296
299
|
|
|
297
|
-
|
|
300
|
+
for (const error of errors) {
|
|
298
301
|
if (!(error instanceof ValidationError)) {
|
|
299
302
|
throw new SyntaxError("Field errors must be a ValidationError");
|
|
300
303
|
}
|
|
301
|
-
}
|
|
304
|
+
}
|
|
302
305
|
|
|
303
306
|
this.#validation[validateObjectKey(pageId)] = errors;
|
|
304
307
|
|
|
@@ -562,7 +565,7 @@ export default class JourneyContext {
|
|
|
562
565
|
}
|
|
563
566
|
|
|
564
567
|
// Initialise new context list in the session
|
|
565
|
-
if (!
|
|
568
|
+
if (!Object.hasOwn(session, "journeyContextList")) {
|
|
566
569
|
log.trace("Initialising session with a default journey context list");
|
|
567
570
|
/* eslint-disable-next-line no-param-reassign */
|
|
568
571
|
session.journeyContextList = [];
|
|
@@ -738,7 +741,7 @@ export default class JourneyContext {
|
|
|
738
741
|
* @returns {Array} Array of contexts
|
|
739
742
|
*/
|
|
740
743
|
static getContexts(session) {
|
|
741
|
-
if (
|
|
744
|
+
if (session && Object.hasOwn(session, "journeyContextList")) {
|
|
742
745
|
return session.journeyContextList.map(([, contextObj]) =>
|
|
743
746
|
JourneyContext.fromObject(contextObj),
|
|
744
747
|
);
|
|
@@ -768,7 +771,7 @@ export default class JourneyContext {
|
|
|
768
771
|
}
|
|
769
772
|
|
|
770
773
|
// Initialise the session if necessary
|
|
771
|
-
if (
|
|
774
|
+
if (Object.hasOwn(session, "journeyContextList") === false) {
|
|
772
775
|
JourneyContext.initContextStore(session);
|
|
773
776
|
}
|
|
774
777
|
|
|
@@ -844,9 +847,9 @@ export default class JourneyContext {
|
|
|
844
847
|
* @returns {void}
|
|
845
848
|
*/
|
|
846
849
|
static removeContextsByTag(session, tag) {
|
|
847
|
-
JourneyContext.getContextsByTag(session, tag)
|
|
848
|
-
JourneyContext.removeContext(session, c)
|
|
849
|
-
|
|
850
|
+
for (const c of JourneyContext.getContextsByTag(session, tag)) {
|
|
851
|
+
JourneyContext.removeContext(session, c);
|
|
852
|
+
}
|
|
850
853
|
}
|
|
851
854
|
|
|
852
855
|
/**
|
|
@@ -856,9 +859,9 @@ export default class JourneyContext {
|
|
|
856
859
|
* @returns {void}
|
|
857
860
|
*/
|
|
858
861
|
static removeContexts(session) {
|
|
859
|
-
JourneyContext.getContexts(session)
|
|
860
|
-
JourneyContext.removeContext(session, c)
|
|
861
|
-
|
|
862
|
+
for (const c of JourneyContext.getContexts(session)) {
|
|
863
|
+
JourneyContext.removeContext(session, c);
|
|
864
|
+
}
|
|
862
865
|
}
|
|
863
866
|
|
|
864
867
|
/**
|
|
@@ -875,13 +878,13 @@ export default class JourneyContext {
|
|
|
875
878
|
JourneyContext.initContextStore(req.session);
|
|
876
879
|
|
|
877
880
|
let contextId;
|
|
878
|
-
if (
|
|
881
|
+
if (req.params && Object.hasOwn(req.params, "contextid")) {
|
|
879
882
|
log.trace("Context ID found in req.params.contextid");
|
|
880
883
|
contextId = String(req.params.contextid);
|
|
881
|
-
} else if (
|
|
884
|
+
} else if (req.query && Object.hasOwn(req.query, "contextid")) {
|
|
882
885
|
log.trace("Context ID found in req.query.contextid");
|
|
883
886
|
contextId = String(req.query.contextid);
|
|
884
|
-
} else if (
|
|
887
|
+
} else if (req.body && Object.hasOwn(req.body, "contextid")) {
|
|
885
888
|
log.trace("Context ID found in req.body.contextid");
|
|
886
889
|
contextId = String(req.body.contextid);
|
|
887
890
|
} else {
|
package/src/lib/MutableRouter.js
CHANGED
|
@@ -84,12 +84,12 @@ export default class MutableRouter {
|
|
|
84
84
|
return this.#router;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
for (const { method, args } of this.#stack) {
|
|
88
88
|
// ESLint disabled as `#router` is dev-controlled, and `seal()` is only
|
|
89
89
|
// run at boot-time before any user interaction
|
|
90
90
|
/* eslint-disable-next-line security/detect-object-injection */
|
|
91
91
|
this.#router[method].call(this.#router, ...args);
|
|
92
|
-
}
|
|
92
|
+
}
|
|
93
93
|
|
|
94
94
|
this.#sealed = true;
|
|
95
95
|
|
package/src/lib/Plan.js
CHANGED
|
@@ -40,10 +40,7 @@ const log = logger("lib:plan");
|
|
|
40
40
|
* @access private
|
|
41
41
|
*/
|
|
42
42
|
function defaultNextFollow(r, context) {
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
Object.prototype.hasOwnProperty.call(v, r.source) && v[r.source] === null
|
|
46
|
-
);
|
|
43
|
+
return context.validation?.[r.source] === null;
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
/**
|
|
@@ -54,10 +51,7 @@ function defaultNextFollow(r, context) {
|
|
|
54
51
|
* @access private
|
|
55
52
|
*/
|
|
56
53
|
function defaultPrevFollow(r, context) {
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
Object.prototype.hasOwnProperty.call(v, r.target) && v[r.target] === null
|
|
60
|
-
);
|
|
54
|
+
return context.validation?.[r.target] === null;
|
|
61
55
|
}
|
|
62
56
|
|
|
63
57
|
/**
|
|
@@ -113,7 +113,7 @@ export default class ValidationError {
|
|
|
113
113
|
// Duplicate parameters to make them available in public scope. These are
|
|
114
114
|
// the values that will be readable, and reflect any context that may have
|
|
115
115
|
// been applied
|
|
116
|
-
Object.keys(originals)
|
|
116
|
+
for (const o of Object.keys(originals)) {
|
|
117
117
|
// ESLint disabled as `o` is an "own" property of `originals`, which is
|
|
118
118
|
// dev-controlled
|
|
119
119
|
/* eslint-disable security/detect-object-injection */
|
|
@@ -123,7 +123,7 @@ export default class ValidationError {
|
|
|
123
123
|
writable: true,
|
|
124
124
|
});
|
|
125
125
|
/* eslint-enable security/detect-object-injection */
|
|
126
|
-
}
|
|
126
|
+
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
@@ -58,13 +58,14 @@ export function validateI18nDirs(dirs = []) {
|
|
|
58
58
|
if (!Array.isArray(dirs)) {
|
|
59
59
|
throw new TypeError("I18n directories must be an array (i18n.dirs)");
|
|
60
60
|
}
|
|
61
|
-
dirs.
|
|
61
|
+
for (let i = 0; i < dirs.length; i++) {
|
|
62
|
+
const dir = dirs[i];
|
|
62
63
|
if (typeof dir !== "string") {
|
|
63
64
|
throw new TypeError(
|
|
64
65
|
`I18n directory must be a string, got ${typeof dir} (i18n.dirs[${i}])`,
|
|
65
66
|
);
|
|
66
67
|
}
|
|
67
|
-
}
|
|
68
|
+
}
|
|
68
69
|
return dirs;
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -81,13 +82,14 @@ export function validateI18nLocales(locales = ["en", "cy"]) {
|
|
|
81
82
|
if (!Array.isArray(locales)) {
|
|
82
83
|
throw new TypeError("I18n locales must be an array (i18n.locales)");
|
|
83
84
|
}
|
|
84
|
-
locales.
|
|
85
|
+
for (let i = 0; i < locales.length; i++) {
|
|
86
|
+
const locale = locales[i];
|
|
85
87
|
if (typeof locale !== "string") {
|
|
86
88
|
throw new TypeError(
|
|
87
89
|
`I18n locale must be a string, got ${typeof locale} (i18n.locales[${i}])`,
|
|
88
90
|
);
|
|
89
91
|
}
|
|
90
|
-
}
|
|
92
|
+
}
|
|
91
93
|
return locales;
|
|
92
94
|
}
|
|
93
95
|
|
|
@@ -146,13 +148,14 @@ export function validateViews(dirs = []) {
|
|
|
146
148
|
if (!Array.isArray(dirs)) {
|
|
147
149
|
throw new TypeError("View directories must be an array (views)");
|
|
148
150
|
}
|
|
149
|
-
dirs.
|
|
151
|
+
for (let i = 0; i < dirs.length; i++) {
|
|
152
|
+
const dir = dirs[i];
|
|
150
153
|
if (typeof dir !== "string") {
|
|
151
154
|
throw new TypeError(
|
|
152
155
|
`View directory must be a string, got ${typeof dir} (views[${i}])`,
|
|
153
156
|
);
|
|
154
157
|
}
|
|
155
|
-
}
|
|
158
|
+
}
|
|
156
159
|
return dirs;
|
|
157
160
|
}
|
|
158
161
|
|
|
@@ -336,7 +339,9 @@ export function validatePageHooks(hooks) {
|
|
|
336
339
|
if (!Array.isArray(hooks)) {
|
|
337
340
|
throw new TypeError("Hooks must be an array");
|
|
338
341
|
}
|
|
339
|
-
|
|
342
|
+
for (let i = 0; i < hooks.length; i++) {
|
|
343
|
+
validatePageHook(hooks[i], i);
|
|
344
|
+
}
|
|
340
345
|
return hooks;
|
|
341
346
|
}
|
|
342
347
|
|
|
@@ -357,7 +362,9 @@ export function validateFields(fields) {
|
|
|
357
362
|
if (!Array.isArray(fields)) {
|
|
358
363
|
throw new TypeError("Page fields must be an array (page[].fields)");
|
|
359
364
|
}
|
|
360
|
-
|
|
365
|
+
for (let i = 0; i < fields.length; i++) {
|
|
366
|
+
validateField(fields[i], i);
|
|
367
|
+
}
|
|
361
368
|
return fields;
|
|
362
369
|
}
|
|
363
370
|
|
|
@@ -384,7 +391,9 @@ export function validatePages(pages = []) {
|
|
|
384
391
|
if (!Array.isArray(pages)) {
|
|
385
392
|
throw new TypeError("Pages must be an array (pages)");
|
|
386
393
|
}
|
|
387
|
-
|
|
394
|
+
for (let i = 0; i < pages.length; i++) {
|
|
395
|
+
validatePage(pages[i], i);
|
|
396
|
+
}
|
|
388
397
|
return pages;
|
|
389
398
|
}
|
|
390
399
|
|
|
@@ -419,12 +428,12 @@ export function validateGlobalHooks(hooks) {
|
|
|
419
428
|
if (hooks === undefined) {
|
|
420
429
|
return [];
|
|
421
430
|
}
|
|
422
|
-
|
|
423
431
|
if (!Array.isArray(hooks)) {
|
|
424
432
|
throw new TypeError("Hooks must be an array");
|
|
425
433
|
}
|
|
426
|
-
|
|
427
|
-
|
|
434
|
+
for (let i = 0; i < hooks.length; i++) {
|
|
435
|
+
validateGlobalHook(hooks[i], i);
|
|
436
|
+
}
|
|
428
437
|
return hooks;
|
|
429
438
|
}
|
|
430
439
|
|
package/src/lib/configure.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MemoryStore } from "express-session";
|
|
2
|
-
import { resolve } from "path";
|
|
3
|
-
import { createRequire } from "module";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
4
|
import cookieParserFactory from "cookie-parser";
|
|
5
5
|
import dirname from "./dirname.cjs";
|
|
6
6
|
|
|
@@ -49,9 +49,9 @@ import { CONFIG_ERROR_VISIBILITY_ONSUBMIT } from "./constants.js";
|
|
|
49
49
|
export default function configure(config = {}) {
|
|
50
50
|
// Pass the raw config through each plugin's configure phase so they can
|
|
51
51
|
// optionally modify it
|
|
52
|
-
(config.plugins ?? [])
|
|
52
|
+
for (const plugin of config.plugins ?? []) {
|
|
53
53
|
plugin.configure(config);
|
|
54
|
-
}
|
|
54
|
+
}
|
|
55
55
|
|
|
56
56
|
// Extract config
|
|
57
57
|
const ingestedConfig = configurationIngestor(config);
|
|
@@ -84,10 +84,13 @@ export default function configure(config = {}) {
|
|
|
84
84
|
} = ingestedConfig;
|
|
85
85
|
|
|
86
86
|
// Prepare all page hooks so they are prefixed with the `journey.` scope.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
for (const page of pages) {
|
|
88
|
+
if (page?.hooks) {
|
|
89
|
+
for (const h of page.hooks) {
|
|
90
|
+
h.hook = `journey.${h.hook}`
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
91
94
|
|
|
92
95
|
// Prepare a Nunjucks environment for rendering all templates.
|
|
93
96
|
// Resolve priority: userland templates > CASA templates > GOVUK templates > Plugin templates
|
|
@@ -207,9 +210,9 @@ export default function configure(config = {}) {
|
|
|
207
210
|
};
|
|
208
211
|
|
|
209
212
|
// Bootstrap all plugins
|
|
210
|
-
plugins
|
|
211
|
-
|
|
212
|
-
|
|
213
|
+
for (const plugin of plugins.filter((p) => p.bootstrap)) {
|
|
214
|
+
plugin?.bootstrap(configOutput)
|
|
215
|
+
}
|
|
213
216
|
|
|
214
217
|
// Finished configuration
|
|
215
218
|
return configOutput;
|
package/src/lib/end-session.js
CHANGED
|
@@ -18,14 +18,14 @@ const log = logger("lib:end-session");
|
|
|
18
18
|
export default function endSession(req, next) {
|
|
19
19
|
const { language } = req.session;
|
|
20
20
|
|
|
21
|
-
Object.
|
|
22
|
-
if (!["cookie"].includes(
|
|
23
|
-
// ESLint disabled as `Object.
|
|
21
|
+
for (const key of Object.keys(req.session)) {
|
|
22
|
+
if (!["cookie"].includes(key)) {
|
|
23
|
+
// ESLint disabled as `Object.keys()` returns "own" properties, and
|
|
24
24
|
// all values are being null'd, so not assigned any user-controlled values
|
|
25
25
|
/* eslint-disable-next-line security/detect-object-injection */
|
|
26
|
-
req.session[
|
|
26
|
+
req.session[key] = null;
|
|
27
27
|
}
|
|
28
|
-
}
|
|
28
|
+
}
|
|
29
29
|
|
|
30
30
|
req.session.save((saveErr) => {
|
|
31
31
|
if (saveErr) {
|
|
@@ -11,7 +11,8 @@ const { all: deepmergeAll } = merge;
|
|
|
11
11
|
const combineMerge = (target, source, options) => {
|
|
12
12
|
const destination = target.slice();
|
|
13
13
|
|
|
14
|
-
source.
|
|
14
|
+
for (let index = 0; index < source.length; index++) {
|
|
15
|
+
const item = source[index];
|
|
15
16
|
// ESLint disabled as `index` is only an integer
|
|
16
17
|
/* eslint-disable security/detect-object-injection */
|
|
17
18
|
if (typeof destination[index] === "undefined") {
|
|
@@ -22,7 +23,7 @@ const combineMerge = (target, source, options) => {
|
|
|
22
23
|
destination.push(item);
|
|
23
24
|
}
|
|
24
25
|
/* eslint-enable security/detect-object-injection */
|
|
25
|
-
}
|
|
26
|
+
}
|
|
26
27
|
return destination;
|
|
27
28
|
};
|
|
28
29
|
|
|
@@ -48,8 +49,7 @@ function isPlainObjectOrArray(o) {
|
|
|
48
49
|
if (isObject(prot) === false) {
|
|
49
50
|
return false;
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
return prot.hasOwnProperty("isPrototypeOf");
|
|
52
|
+
return Object.hasOwn(prot, "isPrototypeOf");
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
function mergeObjects(...objects) {
|
|
@@ -120,7 +120,7 @@ function formatDateObject(date, config = {}) {
|
|
|
120
120
|
function renderAsAttributes(attrsObject) {
|
|
121
121
|
const attrsList = [];
|
|
122
122
|
if (typeof attrsObject === "object") {
|
|
123
|
-
Object.keys(attrsObject)
|
|
123
|
+
for (const key of Object.keys(attrsObject)) {
|
|
124
124
|
// ESLint disable as `attrsObject` is dev-controlled, `Object.keys()` has
|
|
125
125
|
// been used (to get "own" properties) and `m` is one of the characters
|
|
126
126
|
// found by the regex.
|
|
@@ -138,7 +138,7 @@ function renderAsAttributes(attrsObject) {
|
|
|
138
138
|
);
|
|
139
139
|
/* eslint-enable security/detect-object-injection */
|
|
140
140
|
attrsList.push(`${key}="${value}"`);
|
|
141
|
-
}
|
|
141
|
+
}
|
|
142
142
|
}
|
|
143
143
|
return new nunjucks.runtime.SafeString(attrsList.join(" "));
|
|
144
144
|
}
|
package/src/lib/nunjucks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
|
-
import { resolve } from "path";
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
3
|
import { Environment } from "nunjucks";
|
|
4
4
|
import dirname from "./dirname.cjs";
|
|
5
5
|
import CasaTemplateLoader from "./CasaTemplateLoader.js";
|
|
@@ -98,11 +98,11 @@ export default class DateObject extends ValidatorFactory {
|
|
|
98
98
|
formats: ["dd-MMM-yyyy", "dd-MMMM-yyyy"],
|
|
99
99
|
},
|
|
100
100
|
];
|
|
101
|
-
|
|
101
|
+
for (const test of formatTests) {
|
|
102
102
|
if (test.flags.every((v) => v === true)) {
|
|
103
103
|
formats = [...formats, ...test.formats];
|
|
104
104
|
}
|
|
105
|
-
}
|
|
105
|
+
};
|
|
106
106
|
|
|
107
107
|
if (typeof value === "object") {
|
|
108
108
|
formats.find((format) => {
|
|
@@ -145,13 +145,13 @@ export default class DateObject extends ValidatorFactory {
|
|
|
145
145
|
// Check presence of each object component (dd, mm, yyyy) in order to log
|
|
146
146
|
// which specific parts are in error
|
|
147
147
|
errorMsg.focusSuffix = [];
|
|
148
|
-
if (!Object.
|
|
148
|
+
if (!Object.hasOwn(value, "dd") || !value.dd) {
|
|
149
149
|
errorMsg.focusSuffix.push("[dd]");
|
|
150
150
|
}
|
|
151
|
-
if (!Object.
|
|
151
|
+
if (!Object.hasOwn(value, "mm") || !value.mm) {
|
|
152
152
|
errorMsg.focusSuffix.push("[mm]");
|
|
153
153
|
}
|
|
154
|
-
if (!Object.
|
|
154
|
+
if (!Object.hasOwn(value, "yyyy") || !value.yyyy) {
|
|
155
155
|
errorMsg.focusSuffix.push("[yyyy]");
|
|
156
156
|
}
|
|
157
157
|
|
|
@@ -95,13 +95,11 @@ export default class PostalAddressObject extends ValidatorFactory {
|
|
|
95
95
|
// Work out required/optional parts based on config
|
|
96
96
|
const reqF = Object.create(null);
|
|
97
97
|
const reqC = cfg.requiredFields;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
},
|
|
104
|
-
);
|
|
98
|
+
reqF.address1 = reqC.indexOf("address1") > -1;
|
|
99
|
+
reqF.address2 = reqC.indexOf("address2") > -1;
|
|
100
|
+
reqF.address3 = reqC.indexOf("address3") > -1;
|
|
101
|
+
reqF.address4 = reqC.indexOf("address4") > -1;
|
|
102
|
+
reqF.postcode = reqC.indexOf("postcode") > -1;
|
|
105
103
|
|
|
106
104
|
let valid = true;
|
|
107
105
|
const errorMsgs = [];
|
|
@@ -129,9 +127,9 @@ export default class PostalAddressObject extends ValidatorFactory {
|
|
|
129
127
|
};
|
|
130
128
|
// ESLint disabled as `k` is a known value from the constant list above
|
|
131
129
|
/* eslint-disable security/detect-object-injection */
|
|
132
|
-
Object.keys(attributes)
|
|
130
|
+
for (const k of Object.keys(attributes)) {
|
|
133
131
|
const attr = attributes[k];
|
|
134
|
-
const hasProperty = Object.
|
|
132
|
+
const hasProperty = Object.hasOwn(value, k);
|
|
135
133
|
const hasContent = hasProperty && value[k].length > 0;
|
|
136
134
|
|
|
137
135
|
const condMissingOrRegexMismatch =
|
|
@@ -147,7 +145,7 @@ export default class PostalAddressObject extends ValidatorFactory {
|
|
|
147
145
|
}),
|
|
148
146
|
);
|
|
149
147
|
}
|
|
150
|
-
}
|
|
148
|
+
}
|
|
151
149
|
/* eslint-enable security/detect-object-injection */
|
|
152
150
|
} else {
|
|
153
151
|
valid = false;
|
package/src/middleware/data.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
// Decorates the request with some contextual data about the user's journey
|
|
2
2
|
// through the application. This is used by downstream middleware and templates.
|
|
3
3
|
|
|
4
|
-
import lodash from "lodash";
|
|
5
4
|
import JourneyContext from "../lib/JourneyContext.js";
|
|
6
5
|
import { validateUrlPath } from "../lib/utils.js";
|
|
7
6
|
import waypointUrl from "../lib/waypoint-url.js";
|
|
8
7
|
|
|
9
|
-
const { has } = lodash;
|
|
10
|
-
|
|
11
8
|
const editOrigin = (req) => {
|
|
12
|
-
if (
|
|
9
|
+
if (Object.hasOwn(req.query, "editorigin")) {
|
|
13
10
|
return waypointUrl({ waypoint: req.query.editorigin });
|
|
14
11
|
}
|
|
15
|
-
if (
|
|
12
|
+
if (req.body && Object.hasOwn(req.body, "editorigin")) {
|
|
16
13
|
return waypointUrl({ waypoint: req.body.editorigin });
|
|
17
14
|
}
|
|
18
15
|
return "";
|
|
@@ -39,8 +36,8 @@ export default function dataMiddleware({ plan, events, contextIdGenerator }) {
|
|
|
39
36
|
|
|
40
37
|
// Edit mode
|
|
41
38
|
editMode:
|
|
42
|
-
(
|
|
43
|
-
(
|
|
39
|
+
(Object.hasOwn(req.query, "edit") && Object.hasOwn(req.query, "editorigin")) ||
|
|
40
|
+
(Object.hasOwn(req.body, "edit") && Object.hasOwn(req.body, "editorigin")),
|
|
44
41
|
editOrigin: editOrigin(req),
|
|
45
42
|
};
|
|
46
43
|
|