hof 20.0.0-redis-beta.32-redis-beta → 20.0.1
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/.github/workflows/automate-publish.yml +1 -1
- package/.github/workflows/automate-tag.yml +4 -4
- package/README.md +6 -0
- package/components/notify/notify.js +1 -1
- package/config/hof-defaults.js +1 -2
- package/config/sanitisation-rules.js +20 -17
- package/controller/base-controller.js +5 -3
- package/controller/controller.js +5 -0
- package/frontend/template-partials/views/layout.html +2 -2
- package/frontend/template-partials/views/partials/maincontent-left.html +2 -2
- package/frontend/template-partials/views/partials/navigation.html +2 -2
- package/frontend/template-partials/views/partials/summary-table-row.html +2 -2
- package/frontend/template-partials/views/session-timeout.html +2 -1
- package/index.js +1 -1
- package/lib/health.js +1 -1
- package/lib/sessions.js +1 -1
- package/middleware/errors.js +2 -0
- package/middleware/rate-limiter.js +1 -3
- package/package.json +5 -4
- package/sandbox/server.js +1 -1
- package/wizard/middleware/check-progress.js +36 -1
- package/.nyc_output/cb764db8-e9f0-43bb-b3b1-7af57bb79bb5.json +0 -1
- package/.nyc_output/processinfo/cb764db8-e9f0-43bb-b3b1-7af57bb79bb5.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/sandbox/apps/sandbox/translations/en/default.json +0 -224
- package/sandbox/public/css/app.css +0 -2794
- package/sandbox/public/images/icons/icon-caret-left.png +0 -0
- package/sandbox/public/images/icons/icon-complete.png +0 -0
- package/sandbox/public/images/icons/icon-cross-remove-sign.png +0 -0
- package/sandbox/public/js/bundle.js +0 -32888
@@ -7,7 +7,7 @@ jobs:
|
|
7
7
|
runs-on: ubuntu-latest
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
|
-
node-version: [14.x]
|
10
|
+
node-version: [10.x, 12.x, 14.x]
|
11
11
|
redis-version: [4, 5, 6]
|
12
12
|
steps:
|
13
13
|
- uses: actions/checkout@v2.2.0
|
@@ -34,7 +34,7 @@ jobs:
|
|
34
34
|
- uses: actions/checkout@v2.2.0
|
35
35
|
- uses: actions/setup-node@v1
|
36
36
|
with:
|
37
|
-
node-version:
|
37
|
+
node-version: 10
|
38
38
|
registry-url: https://registry.npmjs.org/
|
39
39
|
- run: |
|
40
40
|
git config --local user.email "$(git log --format='%ae' HEAD^!)"
|
@@ -52,7 +52,7 @@ jobs:
|
|
52
52
|
- uses: actions/checkout@v2.2.0
|
53
53
|
- uses: actions/setup-node@v1
|
54
54
|
with:
|
55
|
-
node-version:
|
55
|
+
node-version: 10
|
56
56
|
registry-url: https://registry.npmjs.org/
|
57
57
|
- run: |
|
58
58
|
git config --local user.email "$(git log --format='%ae' HEAD^!)"
|
@@ -70,7 +70,7 @@ jobs:
|
|
70
70
|
- uses: actions/checkout@v2.2.0
|
71
71
|
- uses: actions/setup-node@v1
|
72
72
|
with:
|
73
|
-
node-version:
|
73
|
+
node-version: 10
|
74
74
|
registry-url: https://registry.npmjs.org/
|
75
75
|
- run: |
|
76
76
|
git config --local user.email "$(git log --format='%ae' HEAD^!)"
|
package/README.md
CHANGED
@@ -1722,3 +1722,9 @@ Additional vendor JavaScript files are included. These are:
|
|
1722
1722
|
- safari-cachebuster.js
|
1723
1723
|
|
1724
1724
|
Copy `assets/javascript/vendor` into your javascript directory (ie `hmpo/vendor`) and compile them with your JavaScript.
|
1725
|
+
|
1726
|
+
## Journey Header Navigation.html page
|
1727
|
+
|
1728
|
+
- Navigation.html contains a journeyHeaderURL, which is set in the controller.
|
1729
|
+
- getJourneyHeaderURL within the controller translates an empty baseURL to '/'.
|
1730
|
+
- The above helps fix broken journey header URLs in the GRO and UKVIC services which both have a baseURL's set to '/'.
|
package/config/hof-defaults.js
CHANGED
@@ -27,8 +27,7 @@ const defaults = {
|
|
27
27
|
ignoreMiddlewareLogs: ['/healthz'],
|
28
28
|
redis: {
|
29
29
|
port: process.env.REDIS_PORT || '6379',
|
30
|
-
host: process.env.REDIS_HOST || '127.0.0.1'
|
31
|
-
legacyMode: true
|
30
|
+
host: process.env.REDIS_HOST || '127.0.0.1'
|
32
31
|
},
|
33
32
|
session: {
|
34
33
|
ttl: process.env.SESSION_TTL || 1800,
|
@@ -3,27 +3,30 @@
|
|
3
3
|
|
4
4
|
const sanitisationBlacklistArray = {
|
5
5
|
// Input will be sanitised using the below rules
|
6
|
+
// Each one is an array which will run sequentially
|
7
|
+
// Some have multiple steps which allow us to remove dups then append the suffix
|
8
|
+
// Useful for ensuring we're not re-sanitising the same input multiple times (and appending extra hypens each time)
|
6
9
|
// The key is what we're sanitising out
|
7
10
|
// The regex is the rule we used to find them (note some dictate repeating characters)
|
8
11
|
// And the replace is what we're replacing that pattern with. Usually nothing sometimes a
|
9
12
|
// single character or sometimes a single character followed by a "-"
|
10
|
-
'/*': { regex: '\/\\*', replace: '-' },
|
11
|
-
'*/': { regex: '\\*\\/', replace: '-' },
|
12
|
-
'|': { regex: '\\|', replace: '-' },
|
13
|
-
'&&': { regex: '&&+', replace: '&' },
|
14
|
-
'@@': { regex: '@@+', replace: '@' },
|
15
|
-
'/..;/': { regex: '/\\.\\.;/', replace: '-' }, // Purposely input before ".." as they conflict
|
16
|
-
// '..': { regex: '\\.\\.+', replace: '.' }, // Agreed to disable this rule for now unless its specifically required
|
17
|
-
'/etc/passwd': { regex: '\/etc\/passwd', replace: '-' },
|
18
|
-
'c:\\': { regex: 'c:\\\\', replace: '-' },
|
19
|
-
'cmd.exe': { regex: 'cmd\\.exe', replace: '-' },
|
20
|
-
'<': { regex: '<', replace: '<-' },
|
21
|
-
'>': { regex: '>', replace: '>-' },
|
22
|
-
'[': { regex: '\\[+', replace: '[-' },
|
23
|
-
']': { regex: '\\]+', replace: ']-' },
|
24
|
-
'~': { regex: '~', replace: '~-' },
|
25
|
-
'&#': { regex: '&#', replace: '-' },
|
26
|
-
'%U': { regex: '%U', replace: '-' }
|
13
|
+
'/*': [{ regex: '\/\\*', replace: '-' }],
|
14
|
+
'*/': [{ regex: '\\*\\/', replace: '-' }],
|
15
|
+
'|': [{ regex: '\\|', replace: '-' }],
|
16
|
+
'&&': [{ regex: '&&+', replace: '&' }],
|
17
|
+
'@@': [{ regex: '@@+', replace: '@' }],
|
18
|
+
'/..;/': [{ regex: '/\\.\\.;/', replace: '-' }], // Purposely input before ".." as they conflict
|
19
|
+
// '..': [{ regex: '\\.\\.+', replace: '.' }], // Agreed to disable this rule for now unless its specifically required
|
20
|
+
'/etc/passwd': [{ regex: '\/etc\/passwd', replace: '-' }],
|
21
|
+
'c:\\': [{ regex: 'c:\\\\', replace: '-' }],
|
22
|
+
'cmd.exe': [{ regex: 'cmd\\.exe', replace: '-' }],
|
23
|
+
'<': [{ regex: '<+', replace: '<' }, { regex: '<(?!-)', replace: '<-' }],
|
24
|
+
'>': [{ regex: '>+', replace: '>' }, { regex: '>(?!-)', replace: '>-' }],
|
25
|
+
'[': [{ regex: '\\[+', replace: '[' }, { regex: '\\[(?!-)', replace: '[-' }],
|
26
|
+
']': [{ regex: '\\]+', replace: ']-' }, { regex: '\\](?!-)', replace: ']-' }],
|
27
|
+
'~': [{ regex: '~+', replace: '~' }, { regex: '~(?!-)', replace: '~-' }],
|
28
|
+
'&#': [{ regex: '&#', replace: '-' }],
|
29
|
+
'%U': [{ regex: '%U', replace: '-' }]
|
27
30
|
};
|
28
31
|
|
29
32
|
module.exports = sanitisationBlacklistArray;
|
@@ -177,9 +177,11 @@ module.exports = class BaseController extends EventEmitter {
|
|
177
177
|
// For each property in our form data
|
178
178
|
Object.keys(sanitisationBlacklistArray).forEach(function (blacklisted, blacklistedIndex) {
|
179
179
|
const blacklistedDetail = sanitisationBlacklistArray[blacklisted];
|
180
|
-
|
181
|
-
|
182
|
-
|
180
|
+
blacklistedDetail.forEach(step => {
|
181
|
+
const regexQuery = new RegExp(step.regex, 'gi');
|
182
|
+
// Will perform the required replace based on our passed in regex and the replace string
|
183
|
+
req.form.values[property] = req.form.values[property].replace(regexQuery, step.replace);
|
184
|
+
});
|
183
185
|
});
|
184
186
|
}
|
185
187
|
});
|
package/controller/controller.js
CHANGED
@@ -113,6 +113,7 @@ module.exports = class Controller extends BaseController {
|
|
113
113
|
baseUrl: req.baseUrl,
|
114
114
|
skipToMain: this.getFirstFormItem(req.form.options.fields),
|
115
115
|
title: this.getTitle(route, lookup, req.form.options.fields, res.locals),
|
116
|
+
journeyHeaderURL: this.getJourneyHeaderURL(req.baseUrl),
|
116
117
|
header: this.getHeader(route, lookup, res.locals),
|
117
118
|
captionHeading: this.getCaptionHeading(route, lookup, res.locals),
|
118
119
|
warning: this.getWarning(route, lookup, res.locals),
|
@@ -124,6 +125,10 @@ module.exports = class Controller extends BaseController {
|
|
124
125
|
}, stepLocals);
|
125
126
|
}
|
126
127
|
|
128
|
+
getJourneyHeaderURL(url) {
|
129
|
+
return url === '' ? '/' : url;
|
130
|
+
}
|
131
|
+
|
127
132
|
getFirstFormItem(fields) {
|
128
133
|
let firstFieldKey;
|
129
134
|
if (_.size(fields)) {
|
@@ -44,9 +44,9 @@
|
|
44
44
|
{{/gaTagId}}
|
45
45
|
{{/cookieMessage}}
|
46
46
|
{{$footerSupportLinks}}
|
47
|
-
<ul>
|
47
|
+
<ul class="govuk-footer__inline-list">
|
48
48
|
{{#footerSupportLinks}}
|
49
|
-
<li class="govuk-footer__inline-list-item"><a href="{{path}}">{{#t}}{{property}}{{/t}}</a></li>
|
49
|
+
<li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="{{path}}">{{#t}}{{property}}{{/t}}</a></li>
|
50
50
|
{{/footerSupportLinks}}
|
51
51
|
{{^footerSupportLinks}}
|
52
52
|
<li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="/cookies">{{#t}}base.cookies{{/t}}</a></li>
|
@@ -3,8 +3,8 @@
|
|
3
3
|
<div class="govuk-grid-column-two-thirds">
|
4
4
|
{{$validationSummary}}{{/validationSummary}}
|
5
5
|
{{#captionHeading}}<span class="govuk-caption-l">{{captionHeading}}</span>{{/captionHeading}}
|
6
|
-
{{#header}}<h1 class="govuk-heading-
|
7
|
-
{{#subHeading}}<div id="page-header" class="govuk-heading-
|
6
|
+
{{#header}}<h1 class="govuk-heading-l">{{header}}</h1>{{/header}}
|
7
|
+
{{#subHeading}}<div id="page-header"><h2 class="govuk-heading-m">{{subHeading}}</h2></div>{{/subHeading}}
|
8
8
|
{{$content}}{{/content}}
|
9
9
|
</div>
|
10
10
|
{{/content-outer}}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<div class="govuk-header__content">
|
2
2
|
{{#startPageRedirectUrl}}
|
3
|
-
<a href="{{startPageRedirectUrl}}" class="govuk-header__link govuk-header__link--service-name" id="proposition-name">{{$journeyHeader}}{{/journeyHeader}}</a>
|
3
|
+
<a href="{{startPageRedirectUrl}}" class="govuk-header__link govuk-header__link--service-name" id="proposition-name">{{$journeyHeader}}{{/journeyHeader}}</a>
|
4
4
|
{{/startPageRedirectUrl}}
|
5
5
|
{{^startPageRedirectUrl}}
|
6
|
-
<a href="{{
|
6
|
+
<a href="{{journeyHeaderURL}}" class="govuk-header__link govuk-header__link--service-name" id="proposition-name">{{$journeyHeader}}{{/journeyHeader}}</a>
|
7
7
|
{{/startPageRedirectUrl}}
|
8
8
|
</div>
|
@@ -5,10 +5,10 @@
|
|
5
5
|
<dt class="confirm-label">{{label}}</dt>
|
6
6
|
<dd class="confirm-value" data-value="{{value}}">{{value}}</dd>
|
7
7
|
{{#changeLink}}
|
8
|
-
<dd><span class="link"
|
8
|
+
<dd><span><a class="govuk-link" href="{{changeLink}}" id="{{field}}-change-{{index}}">{{#t}}buttons.change{{/t}} <span class="visuallyhidden">{{changeLinkDescription}} from {{value}}</span></a></span></dd>
|
9
9
|
{{/changeLink}}
|
10
10
|
{{^changeLink}}
|
11
|
-
<dd><span class="link"
|
11
|
+
<dd><span><a class="govuk-link" href="{{baseUrl}}{{step}}/edit#{{field}}" id="{{field}}-change">{{#t}}buttons.change{{/t}} <span class="visuallyhidden">{{changeLinkDescription}} from {{value}}</span></a></span></dd>
|
12
12
|
{{/changeLink}}
|
13
13
|
{{/isSeparator}}
|
14
14
|
</div>
|
@@ -1,6 +1,7 @@
|
|
1
1
|
{{<error}}
|
2
2
|
{{$content}}
|
3
|
-
<
|
3
|
+
<h1 class="govuk-heading-l">{{{content.title}}}</h1>
|
4
|
+
<h2 class="govuk-heading-m">{{{content.message}}}</h2>
|
4
5
|
<a href="{{startLink}}" class="govuk-button" role="button">{{#t}}buttons.start-again{{/t}}</a>
|
5
6
|
{{/content}}
|
6
7
|
{{/error}}
|
package/index.js
CHANGED
@@ -79,7 +79,7 @@ const getContentSecurityPolicy = (config, res) => {
|
|
79
79
|
fontSrc: ['fonts.gstatic.com '],
|
80
80
|
scriptSrc: ['www.google-analytics.com', 'ssl.google-analytics.com'],
|
81
81
|
imgSrc: ['www.google-analytics.com', 'ssl.gstatic.com'],
|
82
|
-
connectSrc: ['www.google-analytics.com']
|
82
|
+
connectSrc: ['https://www.google-analytics.com', 'https://region1.google-analytics.com']
|
83
83
|
};
|
84
84
|
|
85
85
|
if (config.gaTagId) {
|
package/lib/health.js
CHANGED
package/lib/sessions.js
CHANGED
package/middleware/errors.js
CHANGED
@@ -12,6 +12,8 @@ const getContent = (err, translate) => {
|
|
12
12
|
if (err.code === 'SESSION_TIMEOUT') {
|
13
13
|
err.status = 401;
|
14
14
|
err.template = 'session-timeout';
|
15
|
+
err.title = (translate && translate('errors.session.title'));
|
16
|
+
err.message = (translate && translate('errors.session.message'));
|
15
17
|
content.title = (translate && translate('errors.session.title'));
|
16
18
|
content.message = (translate && translate('errors.session.message'));
|
17
19
|
}
|
@@ -25,11 +25,9 @@ module.exports = (options, rateLimitType) => {
|
|
25
25
|
}
|
26
26
|
|
27
27
|
const closeConnection = async err => {
|
28
|
-
await redisClient.
|
28
|
+
await redisClient.quit();
|
29
29
|
return next(err);
|
30
30
|
};
|
31
|
-
redisClient.on('error', err => logger.log('error', err));
|
32
|
-
await redisClient.connect();
|
33
31
|
|
34
32
|
try {
|
35
33
|
// fetch records of current user using IP address, returns null when no record is found
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "hof",
|
3
3
|
"description": "A bootstrap for HOF projects",
|
4
|
-
"version": "20.0.
|
4
|
+
"version": "20.0.1",
|
5
5
|
"license": "MIT",
|
6
6
|
"main": "index.js",
|
7
7
|
"author": "HomeOffice",
|
@@ -42,7 +42,7 @@
|
|
42
42
|
"callsite": "^1.0.0",
|
43
43
|
"chalk": "^2.0.0",
|
44
44
|
"chokidar": "^3.4.0",
|
45
|
-
"connect-redis": "^
|
45
|
+
"connect-redis": "^5.2.0",
|
46
46
|
"cookie-parser": "^1.4.6",
|
47
47
|
"cp": "^0.2.0",
|
48
48
|
"csrf": "^3.0.2",
|
@@ -72,7 +72,7 @@
|
|
72
72
|
"minimatch": "^3.0.3",
|
73
73
|
"minimist": "^1.2.6",
|
74
74
|
"mixwith": "^0.1.1",
|
75
|
-
"moment": "^2.29.
|
75
|
+
"moment": "^2.29.4",
|
76
76
|
"morgan": "^1.10.0",
|
77
77
|
"mustache": "^2.3.0",
|
78
78
|
"nodemailer": "^6.6.3",
|
@@ -80,7 +80,7 @@
|
|
80
80
|
"nodemailer-smtp-transport": "^2.7.4",
|
81
81
|
"nodemailer-stub-transport": "^1.1.0",
|
82
82
|
"notifications-node-client": "^5.1.1",
|
83
|
-
"redis": "^
|
83
|
+
"redis": "^3.1.2",
|
84
84
|
"reqres": "^3.0.1",
|
85
85
|
"request": "^2.79.0",
|
86
86
|
"rimraf": "^3.0.2",
|
@@ -89,6 +89,7 @@
|
|
89
89
|
"uglify-js": "^3.14.3",
|
90
90
|
"underscore": "^1.12.1",
|
91
91
|
"urijs": "^1.19.11",
|
92
|
+
"uuid": "^8.3.2",
|
92
93
|
"winston": "^3.7.2"
|
93
94
|
},
|
94
95
|
"devDependencies": {
|
package/sandbox/server.js
CHANGED
@@ -28,6 +28,41 @@ module.exports = (route, controller, steps, begin) => {
|
|
28
28
|
return _.uniq(allSteps);
|
29
29
|
};
|
30
30
|
|
31
|
+
// Gets all the possible routes
|
32
|
+
const walkAllPossibleSteps = (stepName, allStepsInService, allVisitedSteps) => {
|
33
|
+
const stepIncludingFieldsAndForks = allStepsInService[stepName];
|
34
|
+
if (!stepIncludingFieldsAndForks) { return; }
|
35
|
+
|
36
|
+
const forkTargets = _.map(stepIncludingFieldsAndForks.forks, 'target') || [];
|
37
|
+
const nextStep = stepIncludingFieldsAndForks.next || '';
|
38
|
+
|
39
|
+
// If there is no next step or fork, then we have reached the end of the journey
|
40
|
+
if (!forkTargets.length && !nextStep) {
|
41
|
+
allVisitedSteps.push(stepName);
|
42
|
+
// eslint-disable-next-line consistent-return
|
43
|
+
return _.uniq(allVisitedSteps);
|
44
|
+
}
|
45
|
+
|
46
|
+
const nextStepsAndForks = _.uniq(forkTargets.concat(nextStep));
|
47
|
+
|
48
|
+
// We need to transverse through all 'Next' and 'Forks' for this route
|
49
|
+
nextStepsAndForks.map(each => {
|
50
|
+
if (!allVisitedSteps.includes(each)) {
|
51
|
+
allVisitedSteps.push(each);
|
52
|
+
walkAllPossibleSteps(each, allStepsInService, allVisitedSteps);
|
53
|
+
}
|
54
|
+
});
|
55
|
+
};
|
56
|
+
|
57
|
+
// Create a list of all visited steps
|
58
|
+
const createAllVisitedSteps = (stepName, allStepsInService) => {
|
59
|
+
const allVisitedSteps = [stepName];
|
60
|
+
if (allStepsInService[stepName]) {
|
61
|
+
walkAllPossibleSteps(stepName, allStepsInService, allVisitedSteps);
|
62
|
+
}
|
63
|
+
return _.uniq(allVisitedSteps);
|
64
|
+
};
|
65
|
+
|
31
66
|
const invalidateStep = (stepName, scopedSteps, sessionModel) => {
|
32
67
|
debug('Invalidating', stepName);
|
33
68
|
const step = scopedSteps[stepName] || {};
|
@@ -55,7 +90,7 @@ module.exports = (route, controller, steps, begin) => {
|
|
55
90
|
debug('next', nextStep);
|
56
91
|
debug('potential paths', potentialPaths);
|
57
92
|
// if we're following a loop then allow the loop to be invalidated
|
58
|
-
const whitelist = isLoop(nextStep, req.path) ? [route] :
|
93
|
+
const whitelist = isLoop(nextStep, req.path) ? [route] : createAllVisitedSteps(nextStep, steps);
|
59
94
|
// aggregate all potential journeys from the invalidating step
|
60
95
|
const invalidateSteps = potentialPaths.reduce((arr, step) => arr.concat(getAllPossibleSteps(step, steps)), []);
|
61
96
|
|