@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
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ensure the user is on the right track in their journey through the app. This
|
|
3
|
-
* middleware prevents skipping pages in the journey without having filled in
|
|
4
|
-
* required data in the preceding pages.
|
|
5
|
-
*
|
|
6
|
-
* Enhances `res.locals.casa` with:
|
|
7
|
-
* string journeyPreviousUrl = Absolute URL to the previous page in the journey
|
|
8
|
-
* (if applicable).
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const createLogger = require('../../lib/Logger.js');
|
|
12
|
-
const JourneyContext = require('../../lib/JourneyContext.js');
|
|
13
|
-
const { createGetRequest } = require('../../lib/utils/index.js');
|
|
14
|
-
|
|
15
|
-
module.exports = (mountUrl = '/', plan) => {
|
|
16
|
-
if (!plan) {
|
|
17
|
-
return (req, res, next) => next();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return (req, res, next) => {
|
|
21
|
-
const logger = createLogger('page.journey-rails');
|
|
22
|
-
logger.setSessionId(req.session.id);
|
|
23
|
-
|
|
24
|
-
req.casa = req.casa || Object.create(null);
|
|
25
|
-
|
|
26
|
-
// We can skip to next route handler if the waypoint doesn't feature in the
|
|
27
|
-
// defined user journey.
|
|
28
|
-
if (!plan.containsWaypoint(req.casa.journeyWaypointId)) {
|
|
29
|
-
next();
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Traverse all routes from a given origin. This gives us the list of
|
|
34
|
-
// waypoints that the user could have legitimately visited.
|
|
35
|
-
const traversalOptions = {
|
|
36
|
-
startWaypoint: req.casa.journeyOrigin.waypoint,
|
|
37
|
-
};
|
|
38
|
-
const traversed = plan.traverse(
|
|
39
|
-
req.casa.journeyContext || new JourneyContext(),
|
|
40
|
-
traversalOptions,
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
// Common attributes for generating links
|
|
44
|
-
const requestAttributes = {
|
|
45
|
-
mountUrl,
|
|
46
|
-
editMode: req.inEditMode,
|
|
47
|
-
editOrigin: req.editOriginUrl,
|
|
48
|
-
contextId: req.casa.journeyContext.identity.id,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// The requested waypoint cannot be found in the list of traversed routes;
|
|
52
|
-
// send the user back to their last visited waypoint
|
|
53
|
-
const currentUrlIndex = traversed.indexOf(req.casa.journeyWaypointId);
|
|
54
|
-
if (currentUrlIndex === -1) {
|
|
55
|
-
const redirectUrl = createGetRequest({
|
|
56
|
-
...requestAttributes,
|
|
57
|
-
waypoint: `${req.casa.journeyOrigin.originId || ''}/${traversed[traversed.length - 1]}`,
|
|
58
|
-
});
|
|
59
|
-
logger.debug('Traversal redirect: %s to %s', req.casa.journeyWaypointId, redirectUrl);
|
|
60
|
-
res.status(302).redirect(`${redirectUrl}#`);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// The requested waypoint is reachable via the traversed routes; generate a
|
|
65
|
-
// previous waypoint URL that can be used to navigate back.
|
|
66
|
-
if (currentUrlIndex > 0) {
|
|
67
|
-
res.locals.casa.journeyPreviousUrl = createGetRequest({
|
|
68
|
-
...requestAttributes,
|
|
69
|
-
waypoint: `${req.casa.journeyOrigin.originId || ''}/${traversed[currentUrlIndex - 1]}`,
|
|
70
|
-
});
|
|
71
|
-
next();
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// We're at the very first waypoint that is reachable from the given origin;
|
|
76
|
-
// check if there is a "prev" route available that points to a different
|
|
77
|
-
// origin, that we can use to generate a URL pointing to that waypoint.
|
|
78
|
-
// First, attempt to traverse backwards; this will ensure the route conditions
|
|
79
|
-
// are taken into account during that traversal.
|
|
80
|
-
// If no valid route is found with that method, fallback to using the first
|
|
81
|
-
// `prev` route that we can find.
|
|
82
|
-
const stopCondition = (r) => (r.label.targetOrigin !== undefined);
|
|
83
|
-
let [previousRoute] = plan.traversePrevRoutes(req.casa.journeyContext, {
|
|
84
|
-
startWaypoint: req.casa.journeyWaypointId,
|
|
85
|
-
stopCondition,
|
|
86
|
-
}).filter(stopCondition);
|
|
87
|
-
|
|
88
|
-
if (!previousRoute) {
|
|
89
|
-
[previousRoute] = plan.getPrevOutwardRoutes(req.casa.journeyWaypointId).filter(stopCondition);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (previousRoute) {
|
|
93
|
-
res.locals.casa.journeyPreviousUrl = createGetRequest({
|
|
94
|
-
...requestAttributes,
|
|
95
|
-
mountUrl,
|
|
96
|
-
waypoint: `${previousRoute.label.targetOrigin}/${previousRoute.target}`,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
next();
|
|
101
|
-
};
|
|
102
|
-
};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhances `req.casa` with:
|
|
3
|
-
* string journeyWaypointId = Converts requested URL into a string suitable for
|
|
4
|
-
* use as a journey waypoint ID (i.e. Remove trailing slashes)
|
|
5
|
-
* object journeyOrigin = The origin from which traversals should start
|
|
6
|
-
* Plan plan = The grand Plan.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { parseRequest, createGetRequest } = require('../../lib/utils/index.js');
|
|
10
|
-
|
|
11
|
-
function getSingleOriginMeta(origins, casaRequest) {
|
|
12
|
-
// Even though single-origin Plans won't generally generate URLs with the
|
|
13
|
-
// origin ID included, there is a chance that could happen. So here we're
|
|
14
|
-
// making sure to ignore it if it's there.
|
|
15
|
-
const [originOrWaypoint, waypoint] = casaRequest.waypoint.split('/');
|
|
16
|
-
|
|
17
|
-
return {
|
|
18
|
-
// Set blank originId to prevent generated URLs containing an origin
|
|
19
|
-
origin: { ...origins[0], originId: '' },
|
|
20
|
-
waypoint: originOrWaypoint === origins[0].originId ? waypoint : originOrWaypoint,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function getMultiOriginMeta(origins, casaRequest) {
|
|
25
|
-
const [originId, waypoint] = casaRequest.waypoint.split('/');
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
origin: origins.find((o) => o.originId === originId),
|
|
29
|
-
waypoint,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
module.exports = (mountUrl, plan) => {
|
|
34
|
-
// Prepare for extracting metadata from each request
|
|
35
|
-
const origins = plan.getOrigins();
|
|
36
|
-
const getOriginAndWaypoint = (origins.length === 1 ? getSingleOriginMeta : getMultiOriginMeta)
|
|
37
|
-
.bind(null, origins);
|
|
38
|
-
|
|
39
|
-
return (req, res, next) => {
|
|
40
|
-
// Extract the Plan origin and current waypoint from the request
|
|
41
|
-
const { origin, waypoint } = getOriginAndWaypoint(parseRequest(req));
|
|
42
|
-
|
|
43
|
-
// Define read-only properties
|
|
44
|
-
req.casa = req.casa || Object.create(null);
|
|
45
|
-
Object.defineProperty(req.casa, 'plan', {
|
|
46
|
-
value: plan,
|
|
47
|
-
configurable: false,
|
|
48
|
-
enumerable: true,
|
|
49
|
-
writable: false,
|
|
50
|
-
});
|
|
51
|
-
Object.defineProperty(req.casa, 'journeyOrigin', {
|
|
52
|
-
value: origin,
|
|
53
|
-
configurable: false,
|
|
54
|
-
enumerable: true,
|
|
55
|
-
writable: false,
|
|
56
|
-
});
|
|
57
|
-
Object.defineProperty(req.casa, 'journeyWaypointId', {
|
|
58
|
-
value: waypoint,
|
|
59
|
-
configurable: false,
|
|
60
|
-
enumerable: true,
|
|
61
|
-
writable: false,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Utility function for creating links from within templates
|
|
65
|
-
res.locals.makeLink = (args) => (createGetRequest({
|
|
66
|
-
mountUrl,
|
|
67
|
-
waypoint: `${origin.originId}/${waypoint}`,
|
|
68
|
-
contextId: req.casa.journeyContext.isDefault() ? '' : req.casa.journeyContext.identity.id,
|
|
69
|
-
editMode: req.inEditMode,
|
|
70
|
-
editOrigin: req.editOriginUrl,
|
|
71
|
-
...args,
|
|
72
|
-
}));
|
|
73
|
-
|
|
74
|
-
// Next middleware
|
|
75
|
-
next();
|
|
76
|
-
};
|
|
77
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
const createLogger = require('../../lib/Logger.js');
|
|
2
|
-
const { executeHook } = require('./utils.js');
|
|
3
|
-
|
|
4
|
-
module.exports = (pageMeta = {}) => (req, res, next) => {
|
|
5
|
-
const logger = createLogger('page.render');
|
|
6
|
-
logger.setSessionId(req.session.id);
|
|
7
|
-
const pageId = pageMeta.id;
|
|
8
|
-
const activeContextId = req.casa.journeyContext.isDefault()
|
|
9
|
-
? undefined
|
|
10
|
-
: req.casa.journeyContext.identity.id;
|
|
11
|
-
|
|
12
|
-
req.casa = req.casa || Object.create(null);
|
|
13
|
-
|
|
14
|
-
function renderErrorCallback(err, templateString) {
|
|
15
|
-
if (err) {
|
|
16
|
-
logger.error(err);
|
|
17
|
-
next(err);
|
|
18
|
-
} else {
|
|
19
|
-
res.send(templateString);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function renderGET() {
|
|
24
|
-
res.render(pageMeta.view, {
|
|
25
|
-
formData: req.casa.journeyContext.getDataForPage(pageMeta),
|
|
26
|
-
inEditMode: req.inEditMode,
|
|
27
|
-
editOriginUrl: req.editOriginUrl,
|
|
28
|
-
editSearchParams: req.editSearchParams,
|
|
29
|
-
activeContextId,
|
|
30
|
-
}, renderErrorCallback);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function renderPOST() {
|
|
34
|
-
const errors = req.casa.journeyContext.getValidationErrorsForPage(pageId)
|
|
35
|
-
|| Object.create(null);
|
|
36
|
-
|
|
37
|
-
// This is a convenience for the template. The `govukErrorSummary` macro
|
|
38
|
-
// requires the errors be in a particular format, so here we provide our
|
|
39
|
-
// errors in that format.
|
|
40
|
-
const govukErrors = Object.keys(errors).map((k) => ({
|
|
41
|
-
text: req.i18nTranslator.t(errors[k][0].summary, errors[k][0].variables),
|
|
42
|
-
href: errors[k][0].fieldHref,
|
|
43
|
-
}));
|
|
44
|
-
|
|
45
|
-
// We reflect all POSTed data in req.body rather than just the gathered
|
|
46
|
-
// journey data because the template may have custom fields that aren't part
|
|
47
|
-
// of the formal page data, but are important to how the page functions.
|
|
48
|
-
res.render(pageMeta.view, {
|
|
49
|
-
formData: req.body,
|
|
50
|
-
formErrors: Object.keys(errors).length ? errors : null,
|
|
51
|
-
formErrorsGovukArray: govukErrors.length ? govukErrors : null,
|
|
52
|
-
inEditMode: req.inEditMode,
|
|
53
|
-
editOriginUrl: req.editOriginUrl,
|
|
54
|
-
editSearchParams: req.editSearchParams,
|
|
55
|
-
activeContextId,
|
|
56
|
-
}, renderErrorCallback);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return executeHook(logger, req, res, pageMeta, 'prerender').then(() => {
|
|
60
|
-
logger.trace(
|
|
61
|
-
'Rendering view for %s (editmode=%s, method=%s, contextId=%s)',
|
|
62
|
-
pageId,
|
|
63
|
-
req.inEditMode ? 'true' : 'false',
|
|
64
|
-
req.method,
|
|
65
|
-
req.casa.journeyContext.identity.id,
|
|
66
|
-
);
|
|
67
|
-
if (req.method.toLowerCase() === 'post') {
|
|
68
|
-
renderPOST();
|
|
69
|
-
} else {
|
|
70
|
-
renderGET();
|
|
71
|
-
}
|
|
72
|
-
}).catch((err) => {
|
|
73
|
-
next(err);
|
|
74
|
-
});
|
|
75
|
-
};
|
package/middleware/page/skip.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mark a waypoint as having been viewed, and the user having made an explicit
|
|
3
|
-
* action to pass through it, onto a subsequent page.
|
|
4
|
-
*
|
|
5
|
-
* You may also need to modify the "follow" functions on each of the out-edges
|
|
6
|
-
* leading away from the skipped waypoint, so they understand to allow the skip.
|
|
7
|
-
*
|
|
8
|
-
* It is important that this function overwrites _all_ other data on the
|
|
9
|
-
* specified waypoint.
|
|
10
|
-
*
|
|
11
|
-
* NOTE: All waypoints up to the point of the one being marked must have been
|
|
12
|
-
* visited beforehand, so this middleware must come after journey-rails.
|
|
13
|
-
*
|
|
14
|
-
* Format:
|
|
15
|
-
* /current-waypoint?skipto=next-waypoint.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const JourneyContext = require('../../lib/JourneyContext.js');
|
|
19
|
-
const createLogger = require('../../lib/Logger.js');
|
|
20
|
-
const { createGetRequest } = require('../../lib/utils/index.js');
|
|
21
|
-
|
|
22
|
-
module.exports = (mountUrl) => (req, res, next) => {
|
|
23
|
-
const logger = createLogger('page.skip');
|
|
24
|
-
logger.setSessionId(req.session.id);
|
|
25
|
-
|
|
26
|
-
req.casa = req.casa || Object.create(null);
|
|
27
|
-
|
|
28
|
-
const { skipto } = req.query;
|
|
29
|
-
const { journeyOrigin = { originId: '' } } = req.casa;
|
|
30
|
-
|
|
31
|
-
// Validate arguments
|
|
32
|
-
if (skipto === undefined) {
|
|
33
|
-
next();
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (typeof skipto !== 'string' || !skipto.match(/^[a-z0-9-]{1,200}$/i)) {
|
|
37
|
-
logger.error('Invalid skip waypoint');
|
|
38
|
-
res.status(400).send('Invalid waypoint');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Inject a special "__skipped__" data item into the waypoint's page data,
|
|
43
|
-
// overwriting all other data therein.
|
|
44
|
-
logger.info('Marking waypoint %s as skipped', req.casa.journeyWaypointId);
|
|
45
|
-
req.casa.journeyContext.clearValidationErrorsForPage(req.casa.journeyWaypointId);
|
|
46
|
-
req.casa.journeyContext.setDataForPage(req.casa.journeyWaypointId, {
|
|
47
|
-
__skipped__: true,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Persist changes to session
|
|
51
|
-
JourneyContext.putContext(req.session, req.casa.journeyContext);
|
|
52
|
-
|
|
53
|
-
// Attach edit and contextId flags to the redirect URL, if applicable
|
|
54
|
-
// const redirectUrl
|
|
55
|
-
const redirectUrl = createGetRequest({
|
|
56
|
-
mountUrl,
|
|
57
|
-
waypoint: `${journeyOrigin.originId || ''}/${skipto}`,
|
|
58
|
-
editMode: req.inEditMode,
|
|
59
|
-
editOrigin: req.editOriginUrl,
|
|
60
|
-
contextId: req.casa.journeyContext.identity.id,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Save session and send user on their way
|
|
64
|
-
req.session.save((err) => {
|
|
65
|
-
if (err) {
|
|
66
|
-
logger.error(err);
|
|
67
|
-
next(err);
|
|
68
|
-
} else {
|
|
69
|
-
res.status(302).redirect(redirectUrl);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
};
|
package/middleware/page/utils.js
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
const { isObjectWithKeys, isObjectType, normalizeHtmlObjectPath } = require('../../lib/Util.js');
|
|
2
|
-
const JourneyContext = require('../../lib/JourneyContext.js');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Converts an array of functions to a nested callback, eg:
|
|
6
|
-
* [ | function nested(req, res, next) {-
|
|
7
|
-
* function a(req, res, next) {- | a(req, res, () => {-
|
|
8
|
-
* ... | ...
|
|
9
|
-
* next(); | b(req, res, () => {-
|
|
10
|
-
* }, | ...
|
|
11
|
-
* function b(req, res, next) {- | c(req, res, () => {-
|
|
12
|
-
* ... | ...
|
|
13
|
-
* next(); | next();
|
|
14
|
-
* }, | });
|
|
15
|
-
* function c(req, res, next) {- | })
|
|
16
|
-
* ... | });
|
|
17
|
-
* next(); | }
|
|
18
|
-
* }, |
|
|
19
|
-
* ] |.
|
|
20
|
-
*
|
|
21
|
-
* @param {object} logger Request-specific Logger instance.
|
|
22
|
-
* @param {string} hookName Name of the hook being called.
|
|
23
|
-
* @param {string} waypointId ID of waypoint.
|
|
24
|
-
* @param {Array} hooks Array of middleware like functions.
|
|
25
|
-
* @returns {Function} Nested function.
|
|
26
|
-
*/
|
|
27
|
-
function nestHooks(logger, hookName, waypointId, hooks) {
|
|
28
|
-
return hooks.reduce((inital, hook, hookNumber) => {
|
|
29
|
-
if (typeof hook === 'function') {
|
|
30
|
-
return (req, res, next) => {
|
|
31
|
-
inital(req, res, () => {
|
|
32
|
-
logger.trace('Running %s hook %d for %s', hookName, hookNumber + 1, waypointId);
|
|
33
|
-
hook(req, res, next);
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return inital;
|
|
38
|
-
}, (req, res, next) => next());
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Generic wrapper for executing one of the page hooks.
|
|
43
|
-
*
|
|
44
|
-
* The returned Promise will always resolve unless the hook function ends the
|
|
45
|
-
* response with something like `res.send()`.
|
|
46
|
-
*
|
|
47
|
-
* @param {object} logger Request-specific Logger instance.
|
|
48
|
-
* @param {object} req Express request.
|
|
49
|
-
* @param {object} res Express response.
|
|
50
|
-
* @param {object} pageMeta Metadata of page being processed.
|
|
51
|
-
* @param {string} hookName Name of hook to execute.
|
|
52
|
-
* @returns {Promise} Promise.
|
|
53
|
-
*/
|
|
54
|
-
function executeHook(logger, req = {}, res = {}, pageMeta = {}, hookName = '') {
|
|
55
|
-
return new Promise((resolve, reject) => {
|
|
56
|
-
const hooks = pageMeta && pageMeta.hooks ? pageMeta.hooks : Object.create(null);
|
|
57
|
-
const { journeyWaypointId } = req.casa || Object.create(null);
|
|
58
|
-
if (Array.isArray(hooks[hookName])) {
|
|
59
|
-
const nestedHooks = nestHooks(logger, hookName, req.casa.journeyWaypointId, hooks[hookName]);
|
|
60
|
-
// Will not resolve if any hook executes `res.send()`
|
|
61
|
-
logger.trace('Running nested %s hooks for %s', hookName, journeyWaypointId);
|
|
62
|
-
nestedHooks(req, res, resolve);
|
|
63
|
-
} else if (typeof hooks[hookName] === 'function') {
|
|
64
|
-
logger.trace('Run %s hook for %s', hookName, journeyWaypointId);
|
|
65
|
-
hooks[hookName](req, res, (err) => {
|
|
66
|
-
// Will not resolve if hook executes `res.send()`
|
|
67
|
-
if (err) {
|
|
68
|
-
reject(err);
|
|
69
|
-
} else {
|
|
70
|
-
resolve();
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
} else {
|
|
74
|
-
logger.trace('No %s hook for %s', hookName, journeyWaypointId);
|
|
75
|
-
resolve();
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Apply the `sanitise()` method of each validator rule defined in the
|
|
82
|
-
* fieldValidator. The output of each sanitisation is passed as input to the
|
|
83
|
-
* next.
|
|
84
|
-
*
|
|
85
|
-
* `context` contains the `fieldName`, `waypointId` and `journeyContext`.
|
|
86
|
-
*
|
|
87
|
-
* @param {SimpleFieldValidatorConfig} fieldValidator Validator
|
|
88
|
-
* @param {any} data Data to be sanitised
|
|
89
|
-
* @param {any} context Data context
|
|
90
|
-
* @returns {any} Sanitised data
|
|
91
|
-
*/
|
|
92
|
-
function applyValidatorSanitiser(fieldValidator, data, context) {
|
|
93
|
-
// Apply each valdiator's `sanitise` method
|
|
94
|
-
let sanitisedData = data;
|
|
95
|
-
fieldValidator.validators.forEach((validatorObj) => {
|
|
96
|
-
sanitisedData = validatorObj.sanitise(sanitisedData, context);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
return sanitisedData;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Extract the data that will be saved to session, removing data that does not
|
|
104
|
-
* have an associated field validator.
|
|
105
|
-
*
|
|
106
|
-
* Where no validators are defined for the requested waypoint, we will store
|
|
107
|
-
* nothing in the session.
|
|
108
|
-
*
|
|
109
|
-
* @param {object} logger Request-specific logger instance.
|
|
110
|
-
* @param {object} pageMeta Page meta object.
|
|
111
|
-
* @param {object} data Data to be pruned.
|
|
112
|
-
* @param {JourneyContext} journeyContext Request's journey context.
|
|
113
|
-
* @returns {object} The pruned data.
|
|
114
|
-
* @throws {TypeError} When given invalid argument types.
|
|
115
|
-
*/
|
|
116
|
-
function extractSessionableData(
|
|
117
|
-
logger,
|
|
118
|
-
// pageWaypointId,
|
|
119
|
-
// fieldValidators = {},
|
|
120
|
-
pageMeta,
|
|
121
|
-
data = {},
|
|
122
|
-
journeyContext,
|
|
123
|
-
) {
|
|
124
|
-
if (!isObjectWithKeys(logger, ['warn'])) {
|
|
125
|
-
throw new TypeError('Expected logger to be a configured logging object');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (!isObjectType(pageMeta)) {
|
|
129
|
-
throw new TypeError('Expected pageMeta to be an object');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const { fieldValidators } = pageMeta;
|
|
133
|
-
if (!isObjectWithKeys(fieldValidators)) {
|
|
134
|
-
throw new TypeError('Expected pageMeta.fieldValidators to be an object');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (!isObjectWithKeys(data)) {
|
|
138
|
-
throw new TypeError('Expected data to be an object');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (Object.keys(fieldValidators).length === 0) {
|
|
142
|
-
logger.debug(
|
|
143
|
-
'No field validators defined for "%s" waypoint. Will use an empty object.',
|
|
144
|
-
pageMeta.id,
|
|
145
|
-
);
|
|
146
|
-
return Object.create(null);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Prune data that does not have an associated field valdiator.
|
|
150
|
-
// Conditional functions expect the gathered data to be available via a
|
|
151
|
-
// JourneyContext instance. Therefore we need to create a duplicate of the
|
|
152
|
-
// `journeyContext`, and bundle `data` into it.
|
|
153
|
-
const journeyContextWrapper = JourneyContext.fromObject(journeyContext.toObject());
|
|
154
|
-
journeyContextWrapper.setDataForPage(pageMeta, data);
|
|
155
|
-
const prunedData = Object.create(null);
|
|
156
|
-
Object.keys(fieldValidators).forEach((k) => {
|
|
157
|
-
if (
|
|
158
|
-
typeof data[k] !== 'undefined'
|
|
159
|
-
&& fieldValidators[k].condition({
|
|
160
|
-
fieldName: normalizeHtmlObjectPath(k),
|
|
161
|
-
waypointId: pageMeta.id,
|
|
162
|
-
journeyContext: journeyContextWrapper,
|
|
163
|
-
})
|
|
164
|
-
) {
|
|
165
|
-
prunedData[k] = applyValidatorSanitiser(
|
|
166
|
-
fieldValidators[k],
|
|
167
|
-
data[k],
|
|
168
|
-
{
|
|
169
|
-
fieldName: normalizeHtmlObjectPath(k),
|
|
170
|
-
waypointId: pageMeta.id,
|
|
171
|
-
journeyContext: journeyContextWrapper,
|
|
172
|
-
},
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
return prunedData;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Run modifying functions against the specified field.
|
|
182
|
-
*
|
|
183
|
-
* @param {object} fieldValue Value to modify.
|
|
184
|
-
* @param {Array | Function} gatherModifiers Either an array of functions or a single function.
|
|
185
|
-
* @returns {any} Modified value.
|
|
186
|
-
*/
|
|
187
|
-
function runGatherModifiers(fieldValue, gatherModifiers = []) {
|
|
188
|
-
const modifiers = Array.isArray(gatherModifiers) ? gatherModifiers : [gatherModifiers];
|
|
189
|
-
|
|
190
|
-
let fValue = fieldValue;
|
|
191
|
-
modifiers.forEach((m) => {
|
|
192
|
-
fValue = typeof m === 'function' ? m({
|
|
193
|
-
fieldValue: fValue,
|
|
194
|
-
}) : fValue;
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
return fValue;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
module.exports = {
|
|
201
|
-
applyValidatorSanitiser,
|
|
202
|
-
executeHook,
|
|
203
|
-
extractSessionableData,
|
|
204
|
-
nestHooks,
|
|
205
|
-
runGatherModifiers,
|
|
206
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
const createLogger = require('../../lib/Logger');
|
|
2
|
-
const Validation = require('../../lib/validation/index.js');
|
|
3
|
-
const JourneyContext = require('../../lib/JourneyContext.js');
|
|
4
|
-
const { executeHook } = require('./utils.js');
|
|
5
|
-
|
|
6
|
-
module.exports = (pageMeta = {}) => (req, res, next) => {
|
|
7
|
-
const logger = createLogger('page.validate');
|
|
8
|
-
logger.setSessionId(req.session.id);
|
|
9
|
-
const pageId = pageMeta.id;
|
|
10
|
-
|
|
11
|
-
req.casa = req.casa || Object.create(null);
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Run validation process.
|
|
15
|
-
*
|
|
16
|
-
* @returns {Promise} Promise.
|
|
17
|
-
*/
|
|
18
|
-
function runValidation() {
|
|
19
|
-
let result;
|
|
20
|
-
if (pageMeta && pageMeta.fieldValidators) {
|
|
21
|
-
logger.trace('Run validation for %s', pageId);
|
|
22
|
-
result = Validation.processor({
|
|
23
|
-
waypointId: pageId,
|
|
24
|
-
pageMeta,
|
|
25
|
-
// fieldValidators: pageMeta.fieldValidators,
|
|
26
|
-
journeyContext: req.casa.journeyContext,
|
|
27
|
-
reduceErrors: true,
|
|
28
|
-
});
|
|
29
|
-
} else {
|
|
30
|
-
result = Promise.resolve();
|
|
31
|
-
}
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Promise
|
|
36
|
-
return executeHook(logger, req, res, pageMeta, 'prevalidate')
|
|
37
|
-
.then(runValidation)
|
|
38
|
-
.then(() => (executeHook(logger, req, res, pageMeta, 'postvalidate')))
|
|
39
|
-
.then(() => {
|
|
40
|
-
// Validation has passed, so clear any validation errors currently stored
|
|
41
|
-
// against the page and persist to session
|
|
42
|
-
req.casa.journeyContext.clearValidationErrorsForPage(pageId);
|
|
43
|
-
JourneyContext.putContext(req.session, req.casa.journeyContext);
|
|
44
|
-
|
|
45
|
-
// The next middleware handler is responsible for moving the user onto the
|
|
46
|
-
// correct next waypoint.
|
|
47
|
-
next();
|
|
48
|
-
})
|
|
49
|
-
.catch((errors) => {
|
|
50
|
-
// If it's a real error (i.e. thrown by interpreter rather than application)
|
|
51
|
-
// we want to capture that earlier. Otherwise, treat as a validation error
|
|
52
|
-
if (errors instanceof Error) {
|
|
53
|
-
logger.trace('Passing through system error on waypoint %s: %s', pageId, errors.message);
|
|
54
|
-
next(errors);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Store validation results so they can be used during future traversals
|
|
59
|
-
// TODO: Handle possible exceptions thrown by the below; e.g. if `errors`
|
|
60
|
-
// are not in valid format, an exception is thrown by `setValidationErrorsForPage`
|
|
61
|
-
logger.trace('Storing validation errors on waypoint %s', pageId);
|
|
62
|
-
req.casa.journeyContext.setValidationErrorsForPage(pageId, errors);
|
|
63
|
-
JourneyContext.putContext(req.session, req.casa.journeyContext);
|
|
64
|
-
|
|
65
|
-
next();
|
|
66
|
-
});
|
|
67
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// If the store session has expired, clean up and let the user know. It's
|
|
2
|
-
// important to clear the cookie, using the same options that were used when
|
|
3
|
-
// the cookie was created by expressSession above - see
|
|
4
|
-
// http://expressjs.com/en/api.html#res.clearCookie
|
|
5
|
-
// Session store implementations should have their own clean-up methods to
|
|
6
|
-
// clear out expired sessions, but just in case we also use a `dateExpire`
|
|
7
|
-
// attribute in the session to forcefully destroy server-side sessions after
|
|
8
|
-
// a defined amount of time.
|
|
9
|
-
|
|
10
|
-
const qs = require('querystring');
|
|
11
|
-
const url = require('url');
|
|
12
|
-
const mwInit = require('./init.js');
|
|
13
|
-
|
|
14
|
-
module.exports = (logger, mountUrl = '/', sessionExpiryController, sessionConfig = {}) => (req, res, next) => {
|
|
15
|
-
let redirectPath = `${mountUrl}session-timeout`;
|
|
16
|
-
|
|
17
|
-
// Session already destroyed, or on timeout page
|
|
18
|
-
if (typeof req.session === 'undefined' || req.path === redirectPath) {
|
|
19
|
-
next();
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Update manual expiry timestamp
|
|
24
|
-
let oldSessionId;
|
|
25
|
-
if (req.casaSessionExpired) {
|
|
26
|
-
logger.debug('Auto-removed session %s will be cleared up', req.casaSessionExpired);
|
|
27
|
-
oldSessionId = req.casaSessionExpired;
|
|
28
|
-
delete req.casaSessionExpired;
|
|
29
|
-
} else if (req.session.dateExpire && new Date(req.session.dateExpire).getTime() <= Date.now()) {
|
|
30
|
-
logger.debug('Expired session %s will be destroyed', req.sessionID);
|
|
31
|
-
oldSessionId = req.sessionID;
|
|
32
|
-
} else {
|
|
33
|
-
const ttlMilliseconds = sessionConfig.ttl ? parseInt(sessionConfig.ttl, 10) * 1000 : 0;
|
|
34
|
-
req.session.dateExpire = new Date(Date.now() + ttlMilliseconds).toISOString();
|
|
35
|
-
next();
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Optional redirect after destroy
|
|
40
|
-
function onAfterDestroy() {
|
|
41
|
-
if (!redirectPath || res.headersSent) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Add current path to redirect query
|
|
46
|
-
if (req.originalUrl) {
|
|
47
|
-
const currentUrl = url.parse(req.originalUrl, true);
|
|
48
|
-
const redirectUrl = url.parse(redirectPath, true);
|
|
49
|
-
|
|
50
|
-
// Remove existing referrer query
|
|
51
|
-
if (currentUrl.query.referer) {
|
|
52
|
-
delete currentUrl.query.referer;
|
|
53
|
-
|
|
54
|
-
// Rebuild or remove query string
|
|
55
|
-
currentUrl.search = currentUrl.query.length
|
|
56
|
-
? `?${qs.stringify(currentUrl.query)}`
|
|
57
|
-
: null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Append referrer, rebuild path
|
|
61
|
-
redirectUrl.search = `?${qs.stringify({ referer: url.format(currentUrl) })}`;
|
|
62
|
-
redirectPath = url.format(redirectUrl);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Redirect to session timeout
|
|
66
|
-
res.status(302).redirect(`${redirectPath}#`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Destroy session
|
|
70
|
-
logger.debug('Destroying expired session %s (tmp new ID %s)', oldSessionId, req.sessionID);
|
|
71
|
-
req.session.destroy((err) => {
|
|
72
|
-
if (err) {
|
|
73
|
-
logger.error('Failed to destory session. Error: %s', err.message);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Always clear cookie
|
|
77
|
-
res.clearCookie(sessionConfig.name, {
|
|
78
|
-
path: sessionConfig.cookiePath,
|
|
79
|
-
sameSite: sessionConfig.cookieSameSite,
|
|
80
|
-
httpOnly: true,
|
|
81
|
-
secure: sessionConfig.secure,
|
|
82
|
-
maxAge: null,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Custom expiry controller
|
|
86
|
-
if (typeof sessionExpiryController === 'function') {
|
|
87
|
-
sessionExpiryController(req, res, () => {
|
|
88
|
-
redirectPath = undefined;
|
|
89
|
-
mwInit(logger, sessionConfig)(req, res, next);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
process.nextTick(onAfterDestroy);
|
|
94
|
-
});
|
|
95
|
-
}
|