@dwp/govuk-casa 7.0.6 → 8.0.0-beta1
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/CHANGELOG.md +8 -0
- package/README.md +22 -17
- package/dist/{casa → assets}/css/casa-ie8.css +1 -1
- package/dist/assets/css/casa.css +1 -0
- package/dist/casa.d.ts +11 -0
- package/dist/casa.js +46 -0
- package/dist/lib/CasaTemplateLoader.d.ts +29 -0
- package/dist/lib/CasaTemplateLoader.js +74 -0
- package/dist/lib/JourneyContext.d.ts +297 -0
- package/dist/lib/JourneyContext.js +581 -0
- package/dist/lib/MutableRouter.d.ts +155 -0
- package/dist/lib/MutableRouter.js +277 -0
- package/dist/lib/Plan.d.ts +154 -0
- package/dist/lib/Plan.js +442 -0
- package/dist/lib/ValidationError.d.ts +74 -0
- package/dist/lib/ValidationError.js +159 -0
- package/dist/lib/ValidatorFactory.d.ts +83 -0
- package/dist/lib/ValidatorFactory.js +106 -0
- package/dist/lib/configuration-ingestor.d.ts +262 -0
- package/dist/lib/configuration-ingestor.js +490 -0
- package/dist/lib/configure.d.ts +90 -0
- package/dist/lib/configure.js +192 -0
- package/dist/lib/dirname.cjs +1 -0
- package/dist/lib/dirname.d.cts +2 -0
- package/dist/lib/end-session.d.ts +13 -0
- package/dist/lib/end-session.js +43 -0
- package/dist/lib/field.d.ts +77 -0
- package/dist/lib/field.js +255 -0
- package/dist/lib/index.d.ts +14 -0
- package/dist/lib/index.js +54 -0
- package/dist/lib/logger.d.ts +9 -0
- package/dist/lib/logger.js +18 -0
- package/dist/lib/nunjucks-filters.d.ts +26 -0
- package/dist/lib/nunjucks-filters.js +90 -0
- package/dist/lib/nunjucks.d.ts +23 -0
- package/dist/lib/nunjucks.js +49 -0
- package/dist/lib/utils.d.ts +48 -0
- package/dist/lib/utils.js +111 -0
- package/dist/lib/validators/dateObject.d.ts +4 -0
- package/dist/lib/validators/dateObject.js +135 -0
- package/dist/lib/validators/email.d.ts +4 -0
- package/dist/lib/validators/email.js +46 -0
- package/dist/lib/validators/inArray.d.ts +4 -0
- package/dist/lib/validators/inArray.js +60 -0
- package/dist/lib/validators/index.d.ts +21 -0
- package/dist/lib/validators/index.js +47 -0
- package/dist/lib/validators/nino.d.ts +4 -0
- package/dist/lib/validators/nino.js +46 -0
- package/dist/lib/validators/postalAddressObject.d.ts +4 -0
- package/dist/lib/validators/postalAddressObject.js +123 -0
- package/dist/lib/validators/regex.d.ts +4 -0
- package/dist/lib/validators/regex.js +40 -0
- package/dist/lib/validators/required.d.ts +4 -0
- package/dist/lib/validators/required.js +56 -0
- package/dist/lib/validators/strlen.d.ts +4 -0
- package/dist/lib/validators/strlen.js +51 -0
- package/dist/lib/validators/wordCount.d.ts +5 -0
- package/dist/lib/validators/wordCount.js +54 -0
- package/dist/lib/waypoint-url.d.ts +23 -0
- package/dist/lib/waypoint-url.js +52 -0
- package/dist/middleware/body-parser.d.ts +1 -0
- package/dist/middleware/body-parser.js +24 -0
- package/dist/middleware/csrf.d.ts +1 -0
- package/dist/middleware/csrf.js +31 -0
- package/dist/middleware/data.d.ts +5 -0
- package/dist/middleware/data.js +53 -0
- package/dist/middleware/dirname.cjs +1 -0
- package/dist/middleware/dirname.d.cts +2 -0
- package/dist/middleware/gather-fields.d.ts +6 -0
- package/dist/middleware/gather-fields.js +48 -0
- package/dist/middleware/i18n.d.ts +4 -0
- package/dist/middleware/i18n.js +88 -0
- package/dist/middleware/post.d.ts +3 -0
- package/dist/middleware/post.js +57 -0
- package/dist/middleware/pre.d.ts +3 -0
- package/dist/middleware/pre.js +51 -0
- package/dist/middleware/progress-journey.d.ts +6 -0
- package/dist/middleware/progress-journey.js +80 -0
- package/dist/middleware/sanitise-fields.d.ts +5 -0
- package/dist/middleware/sanitise-fields.js +53 -0
- package/dist/middleware/session.d.ts +11 -0
- package/dist/middleware/session.js +121 -0
- package/dist/middleware/skip-waypoint.d.ts +5 -0
- package/dist/middleware/skip-waypoint.js +43 -0
- package/dist/middleware/steer-journey.d.ts +7 -0
- package/dist/middleware/steer-journey.js +62 -0
- package/dist/middleware/validate-fields.d.ts +7 -0
- package/dist/middleware/validate-fields.js +67 -0
- package/dist/mjs/esm-wrapper.js +11 -0
- package/dist/mjs/package.json +3 -0
- package/dist/package.json +3 -0
- package/dist/routes/ancillary.d.ts +11 -0
- package/dist/routes/ancillary.js +27 -0
- package/dist/routes/dirname.cjs +1 -0
- package/dist/routes/dirname.d.cts +2 -0
- package/dist/routes/journey.d.ts +8 -0
- package/dist/routes/journey.js +127 -0
- package/dist/routes/static.d.ts +26 -0
- package/dist/routes/static.js +68 -0
- package/package.json +64 -89
- package/views/casa/components/checkboxes/template.njk +4 -1
- package/views/casa/components/date-input/template.njk +3 -3
- package/views/casa/components/journey-form/README.md +3 -1
- package/views/casa/components/journey-form/template.njk +1 -1
- package/views/casa/components/postal-address-object/template.njk +5 -5
- package/views/casa/components/radios/template.njk +1 -1
- package/views/casa/errors/static.njk +11 -0
- package/views/casa/layouts/journey.njk +26 -9
- package/views/casa/layouts/main.njk +7 -20
- package/views/casa/partials/scripts.njk +8 -3
- package/views/casa/partials/styles.njk +2 -2
- package/casa.js +0 -208
- package/definitions/review-page.js +0 -60
- package/dist/casa/css/casa.css +0 -1
- package/dist/casa/js/casa.js +0 -1
- package/index.d.ts +0 -121
- package/lib/ConfigIngestor.js +0 -588
- package/lib/GatherModifier.js +0 -14
- package/lib/I18n.js +0 -160
- package/lib/JourneyContext.d.ts +0 -97
- package/lib/JourneyContext.js +0 -552
- package/lib/JourneyMap.js +0 -233
- package/lib/JourneyRoad.js +0 -330
- package/lib/Logger.js +0 -59
- package/lib/PageDictionary.d.ts +0 -11
- package/lib/PageDirectory.js +0 -77
- package/lib/Plan.js +0 -423
- package/lib/RoadConverter.js +0 -153
- package/lib/UserJourney.js +0 -8
- package/lib/Util.js +0 -227
- package/lib/Validation.js +0 -20
- package/lib/bootstrap/end-session.js +0 -44
- package/lib/bootstrap/load-definitions.js +0 -64
- package/lib/commonBodyParser.js +0 -15
- package/lib/enums.js +0 -6
- package/lib/gather-modifiers/index.js +0 -7
- package/lib/gather-modifiers/trimPostalAddressObject.js +0 -75
- package/lib/gather-modifiers/trimWhitespace.js +0 -16
- package/lib/utils/createGetRequest.d.ts +0 -5
- package/lib/utils/createGetRequest.js +0 -59
- package/lib/utils/index.js +0 -11
- package/lib/utils/parseRequest.d.ts +0 -5
- package/lib/utils/parseRequest.js +0 -72
- package/lib/utils/sanitise.js +0 -74
- package/lib/utils/validate.js +0 -32
- package/lib/validation/ArrayObjectField.js +0 -49
- package/lib/validation/ObjectField.js +0 -53
- package/lib/validation/SimpleField.d.ts +0 -11
- package/lib/validation/SimpleField.js +0 -46
- package/lib/validation/ValidationError.d.ts +0 -14
- package/lib/validation/ValidationError.js +0 -170
- package/lib/validation/ValidatorFactory.d.ts +0 -32
- package/lib/validation/ValidatorFactory.js +0 -91
- package/lib/validation/index.js +0 -22
- package/lib/validation/processor/flattenErrorArray.js +0 -24
- package/lib/validation/processor/queue.js +0 -214
- package/lib/validation/processor.js +0 -84
- package/lib/validation/rules/README.md +0 -3
- package/lib/validation/rules/ValidationRules.d.ts +0 -22
- package/lib/validation/rules/dateObject.js +0 -156
- package/lib/validation/rules/email.js +0 -44
- package/lib/validation/rules/inArray.js +0 -61
- package/lib/validation/rules/index.js +0 -23
- package/lib/validation/rules/nino.js +0 -48
- package/lib/validation/rules/optional.js +0 -14
- package/lib/validation/rules/postalAddressObject.js +0 -142
- package/lib/validation/rules/regex.js +0 -39
- package/lib/validation/rules/required.js +0 -57
- package/lib/validation/rules/strlen.js +0 -57
- package/lib/validation/rules/wordCount.js +0 -61
- package/lib/view-filters/formatDateObject.js +0 -35
- package/lib/view-filters/includes.js +0 -10
- package/lib/view-filters/index.js +0 -23
- package/lib/view-filters/mergeObjectsDeep.js +0 -21
- package/lib/view-filters/renderAsAttributes.js +0 -33
- package/middleware/errors/404.js +0 -12
- package/middleware/errors/catch-all.js +0 -27
- package/middleware/errors/index.js +0 -9
- package/middleware/headers/config-defaults.js +0 -57
- package/middleware/headers/headers.js +0 -40
- package/middleware/headers/index.js +0 -9
- package/middleware/i18n/i18n.js +0 -56
- package/middleware/i18n/index.js +0 -16
- package/middleware/index.js +0 -55
- package/middleware/mount/index.js +0 -9
- package/middleware/mount/mount.js +0 -10
- package/middleware/nunjucks/environment.js +0 -57
- package/middleware/nunjucks/index.js +0 -8
- package/middleware/page/csrf.js +0 -37
- package/middleware/page/edit-mode.js +0 -52
- package/middleware/page/gather.js +0 -75
- package/middleware/page/index.js +0 -103
- package/middleware/page/journey-continue.js +0 -157
- package/middleware/page/journey-rails.js +0 -102
- package/middleware/page/prepare-request.js +0 -77
- package/middleware/page/render.js +0 -75
- package/middleware/page/skip.js +0 -72
- package/middleware/page/utils.js +0 -206
- package/middleware/page/validate.js +0 -67
- package/middleware/session/expiry.js +0 -95
- package/middleware/session/genid.js +0 -18
- package/middleware/session/index.js +0 -18
- package/middleware/session/init.js +0 -25
- package/middleware/session/seed.js +0 -50
- package/middleware/session/timeout.js +0 -5
- package/middleware/static/asset-versions.js +0 -23
- package/middleware/static/index.js +0 -104
- package/middleware/static/prepare-assets.js +0 -51
- package/middleware/static/serve-assets.js +0 -58
- package/middleware/variables/index.js +0 -12
- package/middleware/variables/variables.js +0 -35
- package/src/browserconfig.xml +0 -5
- package/src/js/casa.js +0 -132
- package/src/scss/_casaElements.scss +0 -11
- package/src/scss/_casaGovukTemplateJinjaPolyfill.scss +0 -39
- package/src/scss/_casaMountUrl.scss +0 -8
- package/src/scss/casa-ie8.scss +0 -3
- package/src/scss/casa.scss +0 -14
- package/test/unit/templates/README.md +0 -5
- package/test/utils/BaseTestWaypoint.js +0 -106
- package/test/utils/concatWaypoints.js +0 -26
- package/test/utils/index.js +0 -6
- package/test/utils/testTraversal.js +0 -90
- package/views/casa/partials/cookie_message.njk +0 -3
- package/views/casa/partials/phase_banner_alpha.njk +0 -8
- package/views/casa/partials/phase_banner_beta.njk +0 -8
- package/views/casa/review/page-block.njk +0 -8
- package/views/casa/review/review.njk +0 -47
package/lib/Util.js
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
const dot = require('dot-object');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const nUrl = require('url');
|
|
5
|
-
const logger = require('./Logger')('util');
|
|
6
|
-
|
|
7
|
-
const OBJECT_TYPE = '[object Object]';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generate an object path string that we can use to traverse an object using
|
|
11
|
-
* `objectPathValue()`.
|
|
12
|
-
*
|
|
13
|
-
* @param {...string} paths Path components.
|
|
14
|
-
* @returns {string} Constructed path.
|
|
15
|
-
*/
|
|
16
|
-
function objectPathString(...paths) {
|
|
17
|
-
let pathString = paths.length ? paths.join('.') : '';
|
|
18
|
-
// FIX: To support unquoted objects, wrap them in quotes
|
|
19
|
-
// TASK: Contribute this back to vendor repo.
|
|
20
|
-
pathString = pathString.replace(/\[([a-zA-Z_]+[a-zA-Z0-9_]*)\]/g, '["$1"]');
|
|
21
|
-
return pathString;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Find the value at the given path of an object. For example, given the
|
|
26
|
-
* object ...
|
|
27
|
-
* {
|
|
28
|
-
* rooms: {
|
|
29
|
-
* lounge: {
|
|
30
|
-
* objects: [
|
|
31
|
-
* 'TV'
|
|
32
|
-
* ]
|
|
33
|
-
* }
|
|
34
|
-
* }
|
|
35
|
-
* }
|
|
36
|
-
* ... A call to `objectPathValue(obj, 'rooms[lounge].objects[0]')` would
|
|
37
|
-
* return "TV".
|
|
38
|
-
*
|
|
39
|
-
* @param {object} obj Object to traverse
|
|
40
|
-
* @param {string} paths Path component(s) to use
|
|
41
|
-
* @returns {any} The value of the object, or `undefined` if not found
|
|
42
|
-
* @throws {Error} When given an invalid path
|
|
43
|
-
*/
|
|
44
|
-
function objectPathValue(obj, ...paths) {
|
|
45
|
-
// Using dot-object, it is only used to read from an object. It does not
|
|
46
|
-
// support quoted properties, so need to remove those, e.g. ["property"].
|
|
47
|
-
// dot-object has some quirks, such as `a[b.c]` resolving to `a.b.c`,
|
|
48
|
-
// so we remove any of these to avoid ambiguity.
|
|
49
|
-
const pathString = paths.join('.').replace(/["']/g, '');
|
|
50
|
-
if (pathString.match(/\[[^\]]+\./)) {
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
return dot.pick(pathString, obj);
|
|
56
|
-
} catch (e) {
|
|
57
|
-
logger.debug('Object path is invalid: %s (%s)', pathString, e.message);
|
|
58
|
-
throw e;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Given an object path string generated by `objectPathString()`, create a
|
|
64
|
-
* normalized version that can be used to refer to and name HTML form fields.
|
|
65
|
-
* Specifically, this notation should use plain square braces for objects, with
|
|
66
|
-
* no quotations.
|
|
67
|
-
*
|
|
68
|
-
* @param {string} pathString Path to normalize.
|
|
69
|
-
* @returns {string} Normalized path.
|
|
70
|
-
*/
|
|
71
|
-
function normalizeHtmlObjectPath(pathString) {
|
|
72
|
-
return pathString.replace(/\[["']([^\]]+?)['"]\]/g, '[$1]').replace(/[[\]]/g, '.').replace(/\.+/g, '.').replace(/\.+/g, '][')
|
|
73
|
-
.replace(/\[+$/g, '')
|
|
74
|
-
.replace(/^([^[\]]+)]/g, '$1')
|
|
75
|
-
.replace(/\[([^\]]+)$/g, '[$1]')
|
|
76
|
-
.replace(/\]+/g, ']')
|
|
77
|
-
.replace(/\[+/g, '[');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Determine if value is empty. Recurse over objects.
|
|
82
|
-
*
|
|
83
|
-
• Options:
|
|
84
|
-
* RegExp regexRemove = characters matching this regex are removed before test
|
|
85
|
-
*
|
|
86
|
-
* @param {any} e Value to check
|
|
87
|
-
* @param {object} options Options (see above)
|
|
88
|
-
* @returns {boolean} True if the object is empty
|
|
89
|
-
*/
|
|
90
|
-
function isEmpty(e, options) {
|
|
91
|
-
let val = e;
|
|
92
|
-
if (typeof e === 'string' && options && options.regexRemove) {
|
|
93
|
-
val = e.replace(options.regexRemove, '');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
val === null
|
|
98
|
-
|| typeof val === 'undefined'
|
|
99
|
-
|| (typeof val === 'string' && val === '')
|
|
100
|
-
) {
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
if (Array.isArray(val) || typeof val === 'object') {
|
|
104
|
-
return Object.keys(val).filter((k) => !isEmpty(val[k], options)).length === 0;
|
|
105
|
-
}
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Determine which journey is associated with the "journey" part of the given
|
|
111
|
-
* url. In multiple-journey mode, URLs are formatted as so:
|
|
112
|
-
* /<journey-guid>/<waypoint-id>
|
|
113
|
-
*
|
|
114
|
-
* @param {Array} journeys Array of UserJourney.Map instances
|
|
115
|
-
* @param {string} url URL to parse
|
|
116
|
-
* @returns {UserJourney.Map|null} The associated journey
|
|
117
|
-
*/
|
|
118
|
-
function getJourneyFromUrl(journeys, url) {
|
|
119
|
-
// Single-journeys are not reflected in URLs
|
|
120
|
-
if (journeys.length === 1) {
|
|
121
|
-
return journeys[0];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const urlParts = url.replace(/^\/+/, '').split('/');
|
|
125
|
-
return urlParts.length ? (journeys.find((j) => (j.guid === urlParts[0])) || null) : null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function getPageIdFromUrl(url) {
|
|
129
|
-
return nUrl.parse(url).pathname.replace(/^\/+(.+)$/, '$1').replace(/\/+$/g, '');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function getPageIdFromJourneyUrl(journey, url) {
|
|
133
|
-
const guid = (journey && journey.guid) ? String(journey.guid).replace(/[^a-z0-9-]/ig, '') : undefined;
|
|
134
|
-
const strippedUrl = guid ? url.replace(new RegExp(`^/*${guid}/*`), '/') : url;
|
|
135
|
-
return getPageIdFromUrl(strippedUrl);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function isObjectType(obj) {
|
|
139
|
-
return Object.prototype.toString.call(obj) === OBJECT_TYPE;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function isObjectWithKeys(target, keys = []) {
|
|
143
|
-
const isObject = Object.prototype.toString.call(target) === OBJECT_TYPE;
|
|
144
|
-
let hasKeys = true;
|
|
145
|
-
if (isObject) {
|
|
146
|
-
keys.forEach((k) => {
|
|
147
|
-
hasKeys = hasKeys && Object.prototype.hasOwnProperty.call(target, k);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
return isObject && hasKeys;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function hasProp(obj, prop) {
|
|
154
|
-
return Object.prototype.toString.call(obj) === OBJECT_TYPE
|
|
155
|
-
&& Object.prototype.hasOwnProperty.call(obj, prop);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Discover the root folder of the specified npm module.
|
|
160
|
-
*
|
|
161
|
-
* @param {string} module Name of npm module to go and find.
|
|
162
|
-
* @param {Array} paths Paths to search on for module folder.
|
|
163
|
-
* @returns {string} The absolute path to the named module, if found.
|
|
164
|
-
* @throws Error When the module cannot be found.
|
|
165
|
-
* @throws SyntaxError When the module name contains invalid characters.
|
|
166
|
-
*/
|
|
167
|
-
function resolveModulePath(module = '', paths = []) {
|
|
168
|
-
// Strip rogue chars from module name; only valid npm package names are
|
|
169
|
-
// expected (https://docs.npmjs.com/files/package.json#name)
|
|
170
|
-
const modName = module.replace(/[^a-z0-9\-_.]/ig, '').replace(/\.+/i, '.');
|
|
171
|
-
if (modName !== module) {
|
|
172
|
-
throw new SyntaxError('Module name contains invalid characters');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Look for the module in the same places NodeJS would
|
|
176
|
-
const resolved = paths.filter((p) => fs.existsSync(path.normalize(`${p}/${modName}`)));
|
|
177
|
-
if (resolved.length) {
|
|
178
|
-
return path.normalize(`${resolved[0]}/${modName}`);
|
|
179
|
-
}
|
|
180
|
-
throw new Error(`Cannot resolve module '${module}'`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Test is a value can be stringifed (numbers or strings)
|
|
185
|
-
*
|
|
186
|
-
* @param {any} value Item to test
|
|
187
|
-
* @returns {boolean} Whether the value is stringable or not
|
|
188
|
-
*/
|
|
189
|
-
function isStringable(value) {
|
|
190
|
-
return typeof value === 'string' || typeof value === 'number';
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Coerce an input to a string.
|
|
195
|
-
*
|
|
196
|
-
* @param {any} input Input to be stringified
|
|
197
|
-
* @param {string} fallback Fallback to use if input can't be stringified
|
|
198
|
-
* @returns {string} The stringified input
|
|
199
|
-
*/
|
|
200
|
-
function stringifyInput(input, fallback) {
|
|
201
|
-
// Not using param defaults here as the fallback may be explicitly "undefined"
|
|
202
|
-
const fb = arguments.length === 2 && (isStringable(fallback) || fallback === undefined) ? fallback : '';
|
|
203
|
-
return isStringable(input) ? String(input) : fb;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
module.exports = {
|
|
207
|
-
/**
|
|
208
|
-
* Convert a given URL into an ID that we can use to uniquely identify a
|
|
209
|
-
* specific page. This function will not verify the page ID is valid.
|
|
210
|
-
*
|
|
211
|
-
* @param {string} url Url to parse.
|
|
212
|
-
* @returns {string} Page ID.
|
|
213
|
-
*/
|
|
214
|
-
getPageIdFromUrl,
|
|
215
|
-
getPageIdFromJourneyUrl,
|
|
216
|
-
getJourneyFromUrl,
|
|
217
|
-
objectPathValue,
|
|
218
|
-
objectPathString,
|
|
219
|
-
normalizeHtmlObjectPath,
|
|
220
|
-
isEmpty,
|
|
221
|
-
isObjectType,
|
|
222
|
-
isObjectWithKeys,
|
|
223
|
-
resolveModulePath,
|
|
224
|
-
hasProp,
|
|
225
|
-
stringifyInput,
|
|
226
|
-
isStringable,
|
|
227
|
-
};
|
package/lib/Validation.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @deprecated Do not use this file in new applications.
|
|
3
|
-
*
|
|
4
|
-
* Use this instead:
|
|
5
|
-
* const {
|
|
6
|
-
* validationRules,
|
|
7
|
-
* validationProcessor,
|
|
8
|
-
* arrayObjectFieldValidation,
|
|
9
|
-
* objectFieldValidation,
|
|
10
|
-
* simpleFieldValidation
|
|
11
|
-
* } = require('@dwp/govuk-casa');.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const util = require('util');
|
|
15
|
-
const validation = require('./validation/index.js');
|
|
16
|
-
|
|
17
|
-
module.exports = util.deprecate(
|
|
18
|
-
() => (validation),
|
|
19
|
-
'@dwp/govuk-casa/lib/Validation should be replaced with "const { validationRules, validationProcessor, arrayObjectFieldValidation, objectFieldValidation, simpleFieldValidation } = require(\'@dwp/govuk-casa\')"',
|
|
20
|
-
)();
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* End a session.
|
|
3
|
-
*
|
|
4
|
-
* This will destroy the contents of the session, and generate a new session
|
|
5
|
-
* ID. If you need to persist certain data across sessions, be sure to
|
|
6
|
-
* capture it before calling this function, and re-adding it to the new
|
|
7
|
-
* session (in `req.session`) in your promise resolver function.
|
|
8
|
-
*
|
|
9
|
-
* Certain attributes will be persisted:
|
|
10
|
-
* language
|
|
11
|
-
*
|
|
12
|
-
* @param {object} req HTTP request on which to end the session
|
|
13
|
-
* @returns {Promise} Promise that is resolved once session is fully ended
|
|
14
|
-
*/
|
|
15
|
-
module.exports = function endSession(req = {}) {
|
|
16
|
-
return new Promise((resolve, reject) => {
|
|
17
|
-
let lang;
|
|
18
|
-
if (
|
|
19
|
-
typeof req.session === 'object'
|
|
20
|
-
&& Object.prototype.hasOwnProperty.call(req.session, 'language')
|
|
21
|
-
) {
|
|
22
|
-
lang = req.session.language;
|
|
23
|
-
}
|
|
24
|
-
req.session.regenerate((regenError) => {
|
|
25
|
-
if (typeof lang !== 'undefined') {
|
|
26
|
-
req.session.language = lang;
|
|
27
|
-
}
|
|
28
|
-
if (regenError) {
|
|
29
|
-
reject(regenError);
|
|
30
|
-
} else {
|
|
31
|
-
// Explicitly save the new session and wait until complete to avoid
|
|
32
|
-
// possible race conditions like this:
|
|
33
|
-
// https://github.com/expressjs/session/issues/360
|
|
34
|
-
req.session.save((saveError) => {
|
|
35
|
-
if (saveError) {
|
|
36
|
-
reject(saveError);
|
|
37
|
-
} else {
|
|
38
|
-
resolve();
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
});
|
|
44
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
const PageDirectory = require('../PageDirectory.js');
|
|
2
|
-
const Plan = require('../Plan.js');
|
|
3
|
-
|
|
4
|
-
const mwErrors = require('../../middleware/errors/index.js');
|
|
5
|
-
const mwPage = require('../../middleware/page/index.js');
|
|
6
|
-
const mwSessionTimeout = require('../../middleware/session/timeout.js');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Validate pages and generate a PageDirectory from them.
|
|
10
|
-
*
|
|
11
|
-
* @param {object} pages Page definitions, indexed by page id (url slug).
|
|
12
|
-
* @throws {TypeError} For invalid pages type.
|
|
13
|
-
* @returns {PageDirectory} Pages.
|
|
14
|
-
*/
|
|
15
|
-
function buildPageDirectory(pages = {}) {
|
|
16
|
-
if (Object.prototype.toString.call(pages) !== '[object Object]') {
|
|
17
|
-
throw new TypeError('pages must be an object');
|
|
18
|
-
}
|
|
19
|
-
return new PageDirectory(pages);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Validate journey plan.
|
|
24
|
-
*
|
|
25
|
-
* @param {Plan} plan User journey plan.
|
|
26
|
-
* @throws {TypeError} For invalid argument type.
|
|
27
|
-
* @throws {Error} For invalid arguments.
|
|
28
|
-
* @returns {void}
|
|
29
|
-
*/
|
|
30
|
-
function validatePlan(plan = []) {
|
|
31
|
-
// Validate journey(s)
|
|
32
|
-
// For multiple journeys, all journeys _must_ have a guid, and those guids
|
|
33
|
-
// must be unique.
|
|
34
|
-
// For a single journey, a guid must _not_ be set
|
|
35
|
-
if (!(plan instanceof Plan)) {
|
|
36
|
-
throw new TypeError('Journey plan must be a Plan instance');
|
|
37
|
-
} else if (!plan.getOrigins().length) {
|
|
38
|
-
throw new Error('There must be at least 1 defined origin in the plan');
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Load page and journey definitions. The calling application should call this
|
|
44
|
-
* function once all custom routes and configuration has been put in place -
|
|
45
|
-
* it should be the last call made just before starting the HTTP server.
|
|
46
|
-
*
|
|
47
|
-
* @param {object} pages Page definitions, indexed by page id (url slug).
|
|
48
|
-
* @param {Plan} plan Journey plan definition.
|
|
49
|
-
* @returns {void}
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
module.exports = (app, router, config) => (pages, plan) => {
|
|
53
|
-
// Create PageDirectory
|
|
54
|
-
// Each page is a node in the plan data structure
|
|
55
|
-
const pageDirectory = buildPageDirectory(pages);
|
|
56
|
-
|
|
57
|
-
// Validate journey
|
|
58
|
-
validatePlan(plan);
|
|
59
|
-
|
|
60
|
-
// Mount journey-management middleware
|
|
61
|
-
router.get('/session-timeout', mwSessionTimeout(config.sessions.ttl));
|
|
62
|
-
mwPage(config.mountUrl, router, pageDirectory, plan, config.allowPageEdit, config.useStickyEdit);
|
|
63
|
-
mwErrors(app);
|
|
64
|
-
};
|
package/lib/commonBodyParser.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const bodyParser = require('body-parser');
|
|
2
|
-
|
|
3
|
-
const rProto = /__proto__/i;
|
|
4
|
-
const rPrototype = /prototype[=[\]]/i;
|
|
5
|
-
const rConstructor = /constructor[=[\]]/i;
|
|
6
|
-
|
|
7
|
-
module.exports = bodyParser.urlencoded({
|
|
8
|
-
extended: true,
|
|
9
|
-
verify: (req, res, buf, encoding) => {
|
|
10
|
-
const body = decodeURI(buf.toString(encoding));
|
|
11
|
-
if (rProto.test(body) || rPrototype.test(body) || rConstructor.test(body)) {
|
|
12
|
-
throw new Error('Request body verification failed');
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
});
|
package/lib/enums.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gets the property value and Trims white space from it
|
|
3
|
-
*
|
|
4
|
-
* @param {object} value Address object to mung
|
|
5
|
-
* @param {string} prop file property name
|
|
6
|
-
* @returns {string} munged property
|
|
7
|
-
*/
|
|
8
|
-
function transferAndTrim(value, prop) {
|
|
9
|
-
if (typeof value === 'object' && prop in value && typeof value[prop] === 'string') {
|
|
10
|
-
return value[prop].trim();
|
|
11
|
-
}
|
|
12
|
-
return '';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Reformats a postcode into the standard form, as long as this results in a valid postcode.
|
|
17
|
-
*
|
|
18
|
-
* It removes all the spaces from the postcode, converts it to uppercase and then
|
|
19
|
-
* puts a single space back in to separate the last three characters.
|
|
20
|
-
*
|
|
21
|
-
* We found during user testing that some accessibility software
|
|
22
|
-
* automatically adds spaces when entering letters and numbers, resulting in an invalid post code.
|
|
23
|
-
* So the remedy is to remove all the spaces from the string and then to add one space back.
|
|
24
|
-
*
|
|
25
|
-
* If this results in a valid postcode then great it returns the new postcode
|
|
26
|
-
* If not then it returns the original value.
|
|
27
|
-
*
|
|
28
|
-
* So if someone has made a mistake then they are not asked to correct the reformatted
|
|
29
|
-
* text, but instead are asked to correct their original
|
|
30
|
-
*
|
|
31
|
-
* @param {object} value Address object to test
|
|
32
|
-
* @returns {object} GatherModifiered version of the Address object
|
|
33
|
-
*/
|
|
34
|
-
function reformatPostcodeIfValid(value) {
|
|
35
|
-
// convert to upper case
|
|
36
|
-
let postcode = value.toUpperCase();
|
|
37
|
-
|
|
38
|
-
// remove any double spaces
|
|
39
|
-
postcode = postcode.replace(/\s+/g, '');
|
|
40
|
-
|
|
41
|
-
// add a space in the middle if the user did not add one
|
|
42
|
-
if (postcode.length >= 4) {
|
|
43
|
-
postcode = `${postcode.slice(0, postcode.length - 3)} ${postcode.slice(postcode.length - 3)}`;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const pc = /^(?![QVX])[A-Z]((?![IJZ])[A-Z][0-9](([0-9]?)|([ABEHMNPRVWXY]?))|([0-9]([0-9]?|[ABCDEFGHJKPSTUW]?))) ?[0-9]((?![CIKMOV])[A-Z]){2}$|^(BFPO)[ ]?[0-9]{1,4}$/i;
|
|
47
|
-
|
|
48
|
-
if (pc.test(postcode)) {
|
|
49
|
-
return postcode;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return value;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Works hand in hand with the core CASA `postalAddressObject` form macro.
|
|
57
|
-
*
|
|
58
|
-
* Trims white space from the address items and reformats the post code.
|
|
59
|
-
*
|
|
60
|
-
* @param {object} value Address object to test.
|
|
61
|
-
* @returns {object} GatherModifiered version of the Address object.
|
|
62
|
-
*/
|
|
63
|
-
function trimPostalAddressObject(value) {
|
|
64
|
-
// copy only the expected address properties
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
address1: transferAndTrim(value.fieldValue, 'address1'),
|
|
68
|
-
address2: transferAndTrim(value.fieldValue, 'address2'),
|
|
69
|
-
address3: transferAndTrim(value.fieldValue, 'address3'),
|
|
70
|
-
address4: transferAndTrim(value.fieldValue, 'address4'),
|
|
71
|
-
postcode: reformatPostcodeIfValid(transferAndTrim(value.fieldValue, 'postcode')),
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = trimPostalAddressObject;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TrimWhitespace is the most basic and useful munger.
|
|
3
|
-
* It removes leading and tailing white space from the value.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* @param {any} value Value to munge
|
|
7
|
-
* @returns {string} munged value
|
|
8
|
-
*/
|
|
9
|
-
function trimWhitespace(value) {
|
|
10
|
-
if (typeof value.fieldValue === 'string') {
|
|
11
|
-
return value.fieldValue.trim();
|
|
12
|
-
}
|
|
13
|
-
return value.fieldValue;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = trimWhitespace;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
const { DEFAULT_CONTEXT_ID } = require('../enums.js');
|
|
2
|
-
const { sanitiseWaypoint, sanitiseRelativeUrl, sanitiseContextId } = require('./sanitise.js');
|
|
3
|
-
const { validateMountUrl, validateWaypoint } = require('./validate.js');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Create a URL for use in GET requests, or links.
|
|
7
|
-
*
|
|
8
|
-
* If neither a waypoint or mountUrl is provided, only the query portion of the
|
|
9
|
-
* URL will be returned. This is a convenience for situation where you just want
|
|
10
|
-
* to append a query to an existing URL without regenerating the query each time.
|
|
11
|
-
*
|
|
12
|
-
* @param {object} requestObject Request object
|
|
13
|
-
* @returns {string} URL
|
|
14
|
-
*/
|
|
15
|
-
module.exports = function createGetRequest(requestObject = {}) {
|
|
16
|
-
const {
|
|
17
|
-
waypoint,
|
|
18
|
-
editMode,
|
|
19
|
-
editOrigin,
|
|
20
|
-
contextId,
|
|
21
|
-
skipTo,
|
|
22
|
-
mountUrl,
|
|
23
|
-
} = requestObject;
|
|
24
|
-
|
|
25
|
-
// Mount URL
|
|
26
|
-
let urlPath = '';
|
|
27
|
-
if (mountUrl !== undefined) {
|
|
28
|
-
validateMountUrl(mountUrl);
|
|
29
|
-
urlPath = mountUrl;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Waypoint
|
|
33
|
-
if (waypoint !== undefined) {
|
|
34
|
-
validateWaypoint(waypoint, { withOrigin: true });
|
|
35
|
-
urlPath = `${urlPath}${sanitiseWaypoint(waypoint)}`;
|
|
36
|
-
}
|
|
37
|
-
const url = new URL(urlPath, 'https://base.test');
|
|
38
|
-
|
|
39
|
-
// Edit mode and origin
|
|
40
|
-
if (editMode === true) {
|
|
41
|
-
url.searchParams.set('edit', '');
|
|
42
|
-
if (editOrigin) {
|
|
43
|
-
url.searchParams.set('editorigin', sanitiseRelativeUrl(editOrigin));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Context ID
|
|
48
|
-
if (contextId && contextId !== DEFAULT_CONTEXT_ID) {
|
|
49
|
-
url.searchParams.set('contextid', sanitiseContextId(contextId));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Skip reference
|
|
53
|
-
if (skipTo) {
|
|
54
|
-
url.searchParams.set('skipto', sanitiseWaypoint(skipTo));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Return path / querystring
|
|
58
|
-
return !waypoint && !mountUrl ? url.search : `${url.pathname}${url.search}`;
|
|
59
|
-
};
|
package/lib/utils/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const createGetRequest = require('./createGetRequest.js');
|
|
2
|
-
const parseRequest = require('./parseRequest.js');
|
|
3
|
-
const validate = require('./validate.js');
|
|
4
|
-
const sanitise = require('./sanitise.js');
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
createGetRequest,
|
|
8
|
-
parseRequest,
|
|
9
|
-
...sanitise,
|
|
10
|
-
...validate,
|
|
11
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extract some useful CASA-specific information from the request. The resulting
|
|
3
|
-
* object can be manipulated and used to create new requests using
|
|
4
|
-
* `createGetRequest()` and `createPostRequest()`.
|
|
5
|
-
*
|
|
6
|
-
* NOTE: The mountUrl, or proxyMountUrl will _not_ be extracted as `req.url` is
|
|
7
|
-
* used to extract the details, rather than `req.originalUrl`. We could find
|
|
8
|
-
* the mountUrl by comparing the two, but we would not know whether it was a
|
|
9
|
-
* mountUrl or a proxyMountUrl as we have no access to global config here.
|
|
10
|
-
* ref: https://expressjs.com/en/api.html#req.originalUrl
|
|
11
|
-
*
|
|
12
|
-
* Typical usage:
|
|
13
|
-
* const casaRequestObject = parseRequest(req);
|
|
14
|
-
*
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const { URL } = require('url');
|
|
18
|
-
const { sanitiseWaypoint, sanitiseRelativeUrl, sanitiseContextId } = require('./sanitise.js');
|
|
19
|
-
const { isObjectWithKeys, hasProp } = require('../Util.js');
|
|
20
|
-
|
|
21
|
-
function validateRequest(req) {
|
|
22
|
-
if (!isObjectWithKeys(req, ['method', 'url'])) {
|
|
23
|
-
throw new TypeError('Request object is invalid (must include a method and url)');
|
|
24
|
-
}
|
|
25
|
-
if (!['GET', 'POST'].includes(req.method)) {
|
|
26
|
-
throw new Error('Unsupported, or undefined request method');
|
|
27
|
-
}
|
|
28
|
-
if (req.method === 'GET' && !hasProp(req, 'query')) {
|
|
29
|
-
throw new Error('GET request must have a query attribute');
|
|
30
|
-
}
|
|
31
|
-
if (req.method === 'POST' && !hasProp(req, 'body')) {
|
|
32
|
-
throw new Error('POST request must have a body attribute');
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
module.exports = function parseRequest(req) {
|
|
37
|
-
// Validate
|
|
38
|
-
validateRequest(req);
|
|
39
|
-
|
|
40
|
-
// Extract URL information
|
|
41
|
-
// We use req.url which will _not_ include the mounting URL (or proxy mount)
|
|
42
|
-
const urlObject = new URL(req.url, 'https://base.test');
|
|
43
|
-
const paramsSource = (req.method === 'GET' ? req.query : req.body) || Object.create(null);
|
|
44
|
-
|
|
45
|
-
// waypoint (assume the full path is the waypoint)
|
|
46
|
-
const waypoint = sanitiseWaypoint(decodeURIComponent(urlObject.pathname));
|
|
47
|
-
|
|
48
|
-
// editMode
|
|
49
|
-
const editMode = 'edit' in paramsSource;
|
|
50
|
-
|
|
51
|
-
// editOrigin
|
|
52
|
-
const editOrigin = editMode && paramsSource.editorigin
|
|
53
|
-
? sanitiseRelativeUrl(paramsSource.editorigin)
|
|
54
|
-
: undefined;
|
|
55
|
-
|
|
56
|
-
// contextId
|
|
57
|
-
const contextId = paramsSource.contextid ? sanitiseContextId(paramsSource.contextid) : undefined;
|
|
58
|
-
|
|
59
|
-
// Build sparse object
|
|
60
|
-
const obj = {
|
|
61
|
-
waypoint,
|
|
62
|
-
editMode,
|
|
63
|
-
editOrigin,
|
|
64
|
-
contextId,
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// Sparse result
|
|
68
|
-
return Object.keys(obj).reduce(
|
|
69
|
-
(acc, key) => (obj[key] === undefined ? { ...acc } : { ...acc, [key]: obj[key] }),
|
|
70
|
-
Object.create(null),
|
|
71
|
-
);
|
|
72
|
-
}
|