hof 23.0.0-frontend-v4-beta.13 → 23.0.0-frontend-v4-beta.15
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 +34 -2
- package/README.md +20 -2
- package/build/tasks/watch/index.js +1 -0
- package/components/emailer/emailer.js +3 -3
- package/config/builder-defaults.js +6 -6
- package/config/hof-defaults.js +2 -1
- package/frontend/toolkit/index.js +6 -6
- package/index.js +24 -18
- package/lib/encryption.js +43 -17
- package/lib/sessions.js +5 -2
- package/lib/settings.js +1 -1
- package/package.json +2 -3
- package/sandbox/assets/{rebrand/js → js}/index.js +1 -1
- package/sandbox/assets/{rebrand/scss → scss}/app.scss +1 -1
- package/sandbox/package.json +1 -1
- package/sandbox/public/js/bundle.js +9 -9
- package/sandbox/public/images/passports/new-window-link-blue.png +0 -0
- package/sandbox/public/images/passports/new-window-link.png +0 -0
- package/sandbox/public/images/spinner.gif +0 -0
- /package/frontend/toolkit/assets/{rebrand/images → images}/passports/new-window-link-blue.png +0 -0
- /package/frontend/toolkit/assets/{rebrand/images → images}/passports/new-window-link.png +0 -0
- /package/frontend/toolkit/assets/{rebrand/images → images}/spinner.gif +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/character-count.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/form-focus.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/helpers.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/progressive-reveal.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/validation.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/vendor/details.polyfill.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/vendor/indexof.polyfill.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/javascript → javascript}/vendor/safari-cachebuster.js +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/_base.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/_helpers.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/_layout.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/_typography.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/_variables.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/app.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_buttons.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_details.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_elements-typography.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_forms.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_helpers.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_layout.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_lists.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_panels.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_reset.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_tables.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/forms/_form-block-labels.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/forms/_form-date.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/forms/_form-validation.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/mixins.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_alerts.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_buttons.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_confirm-page.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_lists.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_progressive-reveal.scss +0 -0
- /package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_validation.scss +0 -0
- /package/sandbox/assets/{rebrand/images → images}/icons/icon-caret-left.png +0 -0
- /package/sandbox/assets/{rebrand/images → images}/icons/icon-complete.png +0 -0
- /package/sandbox/assets/{rebrand/images → images}/icons/icon-cross-remove-sign.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## 2025-
|
|
1
|
+
## 2025-12-09, Version 23.0.0 (Stable), @Rhodine-orleans-lindsay
|
|
2
2
|
### Changed
|
|
3
3
|
- Updated cookie banner view to follow GOV.UK design system. Updated cookieSettings.js to allow for different confirmation text based on whether cookies were accepted or rejected
|
|
4
4
|
- Added inputmode='numeric' to date component
|
|
@@ -10,7 +10,39 @@
|
|
|
10
10
|
- Added a modifier for phone text input styles that accept sequences of digits
|
|
11
11
|
- Added govuk-template--rebranded class to govuk template html to enable govuk rebrand styles:
|
|
12
12
|
- Updated header and footer to follow GOV.UK design system as part of rebrand
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
## 2025-11-20, Version 22.12.0 (Stable), @dk4g @jamiecarterHO
|
|
15
|
+
|
|
16
|
+
### Infrastructure
|
|
17
|
+
- Updated CI/CD pipeline to test against Node.js 20.x, 22.x, and 24.x
|
|
18
|
+
- Updated Redis testing versions to 7 and 8
|
|
19
|
+
- Added `NODE_VERSION` environment variable for consistent Node.js version across jobs
|
|
20
|
+
- Updated release process to use Node.js 24 for tagging and publishing operations
|
|
21
|
+
|
|
22
|
+
### Security
|
|
23
|
+
- Replaced deprecated `crypto.createCipher`/`crypto.createDecipher` with `crypto.createCipheriv`/`crypto.createDecipheriv`
|
|
24
|
+
- Added proper initialisation vector (IV) handling for enhanced security
|
|
25
|
+
- Enforced 32-byte session secret requirement for AES-256 encryption compatibility
|
|
26
|
+
- Removed insecure default session secret ('changethis') - now requires explicit configuration
|
|
27
|
+
|
|
28
|
+
### Migration Notes
|
|
29
|
+
- **Session Reset Required**: Due to enhanced encryption security, existing user sessions will be invalidated and users will need to re-authenticate after this update
|
|
30
|
+
- **Session Secret**: You must now set a unique `SESSION_SECRET` environment variable of exactly 32 bytes for encryption compatibility.
|
|
31
|
+
For testing purposes, you can use the following command to generate a random value. For production environments, consult a security expert or refer to official cryptographic guidelines to generate a secure secret
|
|
32
|
+
`node -e "console.log(require('crypto').randomBytes(16).toString('hex'))"`
|
|
33
|
+
|
|
34
|
+
## 2025-11-15, Version 22.11.0 (Stable), @Rhodine-orleans-lindsay
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- Updated custom session-timeout handling so that custom behaviours are not blocked by a `404` middleware error.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
- Added a `CUSTOM_SESSION_EXPIRY` environment variable so that a time other than the redis session ttl can be used for the session timeout. **IMPORTANT**: The `CUSTOM_SESSION_EXPIRY` variable must always be a time before the redis session ttl would expire so that behaviours can run before the `SESSION_TIMEOUT` middleware is triggered.
|
|
41
|
+
- Added a `USE_CUSTOM_SESSION_TIMEOUT` that is `false` by default. When set to `true` the '/session-timeout' page can run before the session expires without triggering a `404` middleware error.
|
|
42
|
+
|
|
43
|
+
- 🎬 Action:
|
|
44
|
+
- For custom session timeout handling that is not linked to the redis session ttl, The following variables must be set: `CUSTOM_SESSION_EXPIRY` to the relevant expiry time e.g.600 and `USE_CUSTOM_SESSION_TIMEOUT` to true.
|
|
45
|
+
- If a behaviour is required on the '/session-timeout` step, the '/session-timeout' step must be set in the project's index.js, along with any relevant behaviours.
|
|
14
46
|
|
|
15
47
|
## 2025-10-10, Version 22.10.4 (Stable), @dk4g
|
|
16
48
|
### Security
|
package/README.md
CHANGED
|
@@ -867,7 +867,7 @@ Kubernetes healthcheck URLs are provided as defaults if no overrides are supplie
|
|
|
867
867
|
|----------|-------------|---------|---------|
|
|
868
868
|
| `SHOW_COOKIES_BANNER` | Controls whether the cookies banner is displayed | Auto-detected based on GA tags | `true`, `false` |
|
|
869
869
|
|
|
870
|
-
**
|
|
870
|
+
**Behaviour:**
|
|
871
871
|
- If `SHOW_COOKIES_BANNER` is explicitly set, that value is used
|
|
872
872
|
- If not set, banner is automatically shown when `GA_TAG` or `GA_4_TAG` is present
|
|
873
873
|
- If no GA tags are configured, banner is hidden by default
|
|
@@ -1328,7 +1328,11 @@ This feature allows you to customise the content related to the session timeout
|
|
|
1328
1328
|
|
|
1329
1329
|
### Usage
|
|
1330
1330
|
|
|
1331
|
-
To
|
|
1331
|
+
By default, the session timeout is set to the redis session ttl. To bypass this and display the session timeout message before the redis session ttl the following evironment variables must be set:
|
|
1332
|
+
`CUSTOM_SESSION_EXPIRY` - e.g. `600`. Configure to expire before thte project's redis session ttl.
|
|
1333
|
+
`USE_CUSTOM_SESSION_TIMEOUT` - `false` by default. When set to `true` the '/session-timeout' page can run before the session expires without triggering a `404` middleware error.
|
|
1334
|
+
|
|
1335
|
+
To enable and customise the session timeout behaviour, you need to set the component and translations in your project's `hof.settings.json` file:
|
|
1332
1336
|
```json
|
|
1333
1337
|
"behaviours": [
|
|
1334
1338
|
"hof/components/session-timeout-warning"
|
|
@@ -1348,6 +1352,20 @@ By default, the framework uses the standard content provided by HOF. If you wish
|
|
|
1348
1352
|
"saveExitFormContent": true // allows you to customise the content on the save-and-exit page
|
|
1349
1353
|
```
|
|
1350
1354
|
|
|
1355
|
+
To override the default session-timeout page completely, the path to the session-timeout.html should be set in the views property in the hof.settings.json file e.g.
|
|
1356
|
+
```json
|
|
1357
|
+
"behaviours": [
|
|
1358
|
+
"hof/components/session-timeout-warning"
|
|
1359
|
+
],
|
|
1360
|
+
"translations": "./apps/common/translations",
|
|
1361
|
+
"views": ["./apps/common/views"], // allows you to overide the HOF default session-timeout page and use a custom one from the specified views
|
|
1362
|
+
...
|
|
1363
|
+
```
|
|
1364
|
+
or in the project's `server.js` e.g.
|
|
1365
|
+
```js
|
|
1366
|
+
settings.views = path.resolve(__dirname, './apps/common/views');
|
|
1367
|
+
```
|
|
1368
|
+
|
|
1351
1369
|
### Customising content in `pages.json`
|
|
1352
1370
|
Once the variables are set, you can customise the session timeout warning and exit messages in your project's pages.json:
|
|
1353
1371
|
|
|
@@ -125,6 +125,7 @@ module.exports = config => {
|
|
|
125
125
|
const rootDir = require('path').resolve(__dirname, '../../../');
|
|
126
126
|
ignored.push(`${rootDir}/frontend/govuk-template/govuk_template_generated.html`);
|
|
127
127
|
watchLocation = [rootDir, '.'];
|
|
128
|
+
process.env.SESSION_SECRET = require('crypto').randomBytes(16).toString('hex');
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
const watcher = chokidar.watch(watchLocation, { ignored });
|
|
@@ -34,17 +34,17 @@ module.exports = class Emailer {
|
|
|
34
34
|
html: body,
|
|
35
35
|
attachments: [{
|
|
36
36
|
filename: 'govuk_logotype_email.png',
|
|
37
|
-
path: path.resolve(__dirname, './assets/
|
|
37
|
+
path: path.resolve(__dirname, './assets/images/govuk_logotype_email.png'),
|
|
38
38
|
cid: 'govuk_logotype_email'
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
filename: 'ho_crest_27px.png',
|
|
42
|
-
path: path.resolve(__dirname, './assets/
|
|
42
|
+
path: path.resolve(__dirname, './assets/images/ho_crest_27px.png'),
|
|
43
43
|
cid: 'ho_crest_27px'
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
filename: 'spacer.gif',
|
|
47
|
-
path: path.resolve(__dirname, './assets/
|
|
47
|
+
path: path.resolve(__dirname, './assets/images/spacer.gif'),
|
|
48
48
|
cid: 'spacer_image'
|
|
49
49
|
}]
|
|
50
50
|
}, (err, result) => err ? reject(err) : resolve(result));
|
|
@@ -6,17 +6,17 @@ const toolkitImages =
|
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
browserify: {
|
|
9
|
-
src: 'assets/
|
|
9
|
+
src: 'assets/js/index.js',
|
|
10
10
|
out: 'public/js/bundle.js',
|
|
11
|
-
match: 'assets/
|
|
11
|
+
match: 'assets/js/**/*.js',
|
|
12
12
|
restart: false,
|
|
13
13
|
compress: false,
|
|
14
14
|
debug: false
|
|
15
15
|
},
|
|
16
16
|
sass: {
|
|
17
|
-
src: 'assets/
|
|
17
|
+
src: 'assets/scss/app.scss',
|
|
18
18
|
out: 'public/css/app.css',
|
|
19
|
-
match: 'assets/
|
|
19
|
+
match: 'assets/scss/**/*.scss',
|
|
20
20
|
restart: false,
|
|
21
21
|
quietDeps: false,
|
|
22
22
|
outputStyle: 'expanded',
|
|
@@ -28,9 +28,9 @@ module.exports = {
|
|
|
28
28
|
shared: 'apps/common/translations/src'
|
|
29
29
|
},
|
|
30
30
|
images: {
|
|
31
|
-
src: ['assets/rebrand/images', toolkitImages],
|
|
31
|
+
src: ['assets/rebrand/images', 'assets/images', toolkitImages],
|
|
32
32
|
out: 'public/images',
|
|
33
|
-
match:
|
|
33
|
+
match: 'assets/images/**/*',
|
|
34
34
|
restart: false
|
|
35
35
|
},
|
|
36
36
|
server: {
|
package/config/hof-defaults.js
CHANGED
|
@@ -51,7 +51,7 @@ const defaults = {
|
|
|
51
51
|
},
|
|
52
52
|
session: {
|
|
53
53
|
ttl: process.env.SESSION_TTL || 1800,
|
|
54
|
-
secret: process.env.SESSION_SECRET
|
|
54
|
+
secret: process.env.SESSION_SECRET,
|
|
55
55
|
name: process.env.SESSION_NAME || 'hod.sid',
|
|
56
56
|
sanitiseInputs: false
|
|
57
57
|
},
|
|
@@ -59,6 +59,7 @@ const defaults = {
|
|
|
59
59
|
pdfConverter: process.env.PDF_CONVERTER_URL
|
|
60
60
|
},
|
|
61
61
|
serveStatic: process.env.SERVE_STATIC_FILES !== 'false',
|
|
62
|
+
useCustomSessionTimeout: parseBoolean(process.env.USE_CUSTOM_SESSION_TIMEOUT, false, 'USE_CUSTOM_SESSION_TIMEOUT'),
|
|
62
63
|
sessionTimeOutWarning: process.env.SESSION_TIMEOUT_WARNING || 300,
|
|
63
64
|
serviceUnavailable: parseBoolean(process.env.SERVICE_UNAVAILABLE, false, 'SERVICE_UNAVAILABLE')
|
|
64
65
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
helpers: require('./assets/
|
|
3
|
-
formFocus: require('./assets/
|
|
4
|
-
progressiveReveal: require('./assets/
|
|
5
|
-
validation: require('./assets/
|
|
2
|
+
helpers: require('./assets/javascript/helpers'),
|
|
3
|
+
formFocus: require('./assets/javascript/form-focus'),
|
|
4
|
+
progressiveReveal: require('./assets/javascript/progressive-reveal'),
|
|
5
|
+
validation: require('./assets/javascript/validation'),
|
|
6
6
|
detailsSummary: function () {
|
|
7
|
-
require('./assets/
|
|
7
|
+
require('./assets/javascript/vendor/details.polyfill');
|
|
8
8
|
},
|
|
9
|
-
characterCount: require('./assets/
|
|
9
|
+
characterCount: require('./assets/javascript/character-count')
|
|
10
10
|
};
|
package/index.js
CHANGED
|
@@ -158,7 +158,7 @@ function bootstrap(options) {
|
|
|
158
158
|
res.locals.htmlLang = config.htmlLang;
|
|
159
159
|
res.locals.cookieName = config.session.name;
|
|
160
160
|
// session timeout warning configs
|
|
161
|
-
res.locals.sessionTimeOut = config.session.ttl;
|
|
161
|
+
res.locals.sessionTimeOut = process.env.CUSTOM_SESSION_EXPIRY || config.session.ttl;
|
|
162
162
|
res.locals.sessionTimeOutWarning = config.sessionTimeOutWarning;
|
|
163
163
|
res.locals.sessionTimeoutWarningContent = config.sessionTimeoutWarningContent;
|
|
164
164
|
res.locals.exitFormContent = config.exitFormContent;
|
|
@@ -238,8 +238,8 @@ function bootstrap(options) {
|
|
|
238
238
|
app.use(hofMiddleware.rateLimiter(config, 'requests'));
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
// Set up routing so <YOUR-SITE-URL>/assets are served from /node_modules/govuk-frontend/govuk/assets
|
|
242
|
-
app.use('/assets', express.static(path.join(__dirname, '/node_modules/govuk-frontend/govuk/assets
|
|
241
|
+
// Set up routing so <YOUR-SITE-URL>/assets are served from /node_modules/govuk-frontend/govuk/assets
|
|
242
|
+
app.use('/assets', express.static(path.join(__dirname, '/node_modules/govuk-frontend/govuk/assets')));
|
|
243
243
|
// Check if service has been paused and redirect accordingly
|
|
244
244
|
const bypassPaths = ['/assets', '/healthcheck', '/service-unavailable'];
|
|
245
245
|
|
|
@@ -254,26 +254,32 @@ function bootstrap(options) {
|
|
|
254
254
|
|
|
255
255
|
/**
|
|
256
256
|
* Handles requests to the session timeout page.
|
|
257
|
+
* For custom session timeout handling that is not linked to the redis session ttl,
|
|
258
|
+
* set `CUSTOM_SESSION_EXPIRY` variables to the relevant time and `USE_CUSTOM_SESSION_TIMEOUT`variables to true.
|
|
259
|
+
* If `CUSTOM_SESSION_EXPIRY` and `USE_CUSTOM_SESSION_TIMEOUT` envs are set,
|
|
260
|
+
* include '/session-timeout' step in the project's index.js.
|
|
257
261
|
* - If the user has a session cookie but their session is missing or inactive,
|
|
258
262
|
* this triggers a session timeout error handled by error middleware.
|
|
259
263
|
* - Otherwise, responds with a 404 "Page Not Found" error.
|
|
260
264
|
* This route ensures the timeout page only appears after an actual session expiry.
|
|
261
265
|
*/
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
266
|
+
if (!config.useCustomSessionTimeout) {
|
|
267
|
+
app.get('/session-timeout', (req, res, next) => {
|
|
268
|
+
if ((req.cookies['hof-wizard-sc']) && (!req.session || req.session.exists !== true)) {
|
|
269
|
+
const err = new Error('Session expired');
|
|
270
|
+
err.code = 'SESSION_TIMEOUT';
|
|
271
|
+
return next(err);
|
|
272
|
+
}
|
|
273
|
+
const err = new Error('Not Found');
|
|
274
|
+
err.status = 404;
|
|
275
|
+
const locals = Object.assign({}, req.translate('errors'));
|
|
276
|
+
if (locals && locals['404']) {
|
|
277
|
+
return res.status(404).render('404', locals['404']);
|
|
278
|
+
}
|
|
279
|
+
// Fallback: render a basic 404 page if translation is missing
|
|
280
|
+
return res.status(404).send('Page Not Found');
|
|
281
|
+
});
|
|
282
|
+
}
|
|
277
283
|
|
|
278
284
|
if (config.getAccessibility === true) {
|
|
279
285
|
deprecate(
|
package/lib/encryption.js
CHANGED
|
@@ -1,23 +1,49 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
1
|
'use strict';
|
|
3
2
|
|
|
4
|
-
const crypto = require('crypto');
|
|
3
|
+
const crypto = require('node:crypto');
|
|
5
4
|
const algorithm = 'aes-256-cbc';
|
|
5
|
+
const ivLength = 16;
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return dec;
|
|
7
|
+
/**
|
|
8
|
+
* Creates an encryption utility with AES-256-CBC algorithm.
|
|
9
|
+
* Provides encrypt and decrypt methods that use a random IV for each encryption operation.
|
|
10
|
+
*
|
|
11
|
+
* @module encryption
|
|
12
|
+
* @param {string|Buffer} secret - Must be exactly 32 bytes
|
|
13
|
+
* @returns {Object} Encryption utility object
|
|
14
|
+
* @throws {Error} If secret is not exactly 32 bytes
|
|
15
|
+
*/
|
|
16
|
+
module.exports = secret => {
|
|
17
|
+
const encryptionKey = Buffer.from(secret, 'utf8');
|
|
18
|
+
if (encryptionKey.byteLength !== 32) {
|
|
19
|
+
throw new Error(`Encryption secret must be exactly 32 bytes. Provided: ${encryptionKey.byteLength} bytes.`);
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
return {
|
|
23
|
+
encrypt: text => {
|
|
24
|
+
try {
|
|
25
|
+
const iv = crypto.randomBytes(ivLength);
|
|
26
|
+
const cipher = crypto.createCipheriv(algorithm, encryptionKey, iv);
|
|
27
|
+
let encrypted = cipher.update(text, 'utf8');
|
|
28
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
29
|
+
return iv.toString('hex') + ':' + encrypted.toString('hex');
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new Error(`Encryption failed: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
decrypt: text => {
|
|
36
|
+
try {
|
|
37
|
+
const textParts = text.split(':');
|
|
38
|
+
const iv = Buffer.from(textParts.shift(), 'hex');
|
|
39
|
+
const encryptedText = Buffer.from(textParts.join(':'), 'hex');
|
|
40
|
+
const decipher = crypto.createDecipheriv(algorithm, encryptionKey, iv);
|
|
41
|
+
let decrypted = decipher.update(encryptedText);
|
|
42
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
43
|
+
return decrypted.toString('utf8');
|
|
44
|
+
} catch (error) {
|
|
45
|
+
throw new Error(`Decryption failed: ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
};
|
package/lib/sessions.js
CHANGED
|
@@ -10,8 +10,11 @@ const secureHttps = config => config.protocol === 'https' || config.env === 'pro
|
|
|
10
10
|
module.exports = (app, config) => {
|
|
11
11
|
const logger = config.logger || console;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const secretBuffer = Buffer.from(config.session.secret, 'utf8');
|
|
14
|
+
if (secretBuffer.byteLength !== 32) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Session secret must be exactly 32 bytes. Current: ${secretBuffer.byteLength} bytes.`
|
|
17
|
+
);
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
app.use(cookieParser(config.session.secret, {
|
package/lib/settings.js
CHANGED
|
@@ -42,7 +42,7 @@ module.exports = async (app, config) => {
|
|
|
42
42
|
viewsArray.slice().reverse().forEach(view => {
|
|
43
43
|
const customViewPath = path.resolve(config.root, view);
|
|
44
44
|
try {
|
|
45
|
-
fs.accessSync(customViewPath, fs.F_OK);
|
|
45
|
+
fs.accessSync(customViewPath, fs.constants.F_OK);
|
|
46
46
|
} catch (err) {
|
|
47
47
|
throw new Error(`Cannot find views at ${customViewPath}`);
|
|
48
48
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hof",
|
|
3
3
|
"description": "A bootstrap for HOF projects",
|
|
4
|
-
"version": "23.0.0-frontend-v4-beta.
|
|
4
|
+
"version": "23.0.0-frontend-v4-beta.15",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"author": "HomeOffice",
|
|
8
8
|
"engines": {
|
|
9
|
-
"node": ">=
|
|
10
|
-
"npm": ">=6.14.0"
|
|
9
|
+
"node": ">=14.0.0"
|
|
11
10
|
},
|
|
12
11
|
"bin": {
|
|
13
12
|
"hof-build": "./bin/hof-build",
|
package/sandbox/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node server.js",
|
|
11
|
-
"start:dev": "HOF_SANDBOX=true ../bin/hof-build watch
|
|
11
|
+
"start:dev": "HOF_SANDBOX=true ../bin/hof-build watch",
|
|
12
12
|
"dev": "yarn && GA_TAG=test nodemon server",
|
|
13
13
|
"build": "HOF_SANDBOX=true ../bin/hof-build",
|
|
14
14
|
"postinstall": "yarn run build"
|
|
@@ -1403,17 +1403,17 @@ module.exports = validation;
|
|
|
1403
1403
|
|
|
1404
1404
|
},{}],12:[function(require,module,exports){
|
|
1405
1405
|
module.exports = {
|
|
1406
|
-
helpers: require('./assets/
|
|
1407
|
-
formFocus: require('./assets/
|
|
1408
|
-
progressiveReveal: require('./assets/
|
|
1409
|
-
validation: require('./assets/
|
|
1406
|
+
helpers: require('./assets/javascript/helpers'),
|
|
1407
|
+
formFocus: require('./assets/javascript/form-focus'),
|
|
1408
|
+
progressiveReveal: require('./assets/javascript/progressive-reveal'),
|
|
1409
|
+
validation: require('./assets/javascript/validation'),
|
|
1410
1410
|
detailsSummary: function () {
|
|
1411
|
-
require('./assets/
|
|
1411
|
+
require('./assets/javascript/vendor/details.polyfill');
|
|
1412
1412
|
},
|
|
1413
|
-
characterCount: require('./assets/
|
|
1413
|
+
characterCount: require('./assets/javascript/character-count')
|
|
1414
1414
|
};
|
|
1415
1415
|
|
|
1416
|
-
},{"./assets/
|
|
1416
|
+
},{"./assets/javascript/character-count":6,"./assets/javascript/form-focus":7,"./assets/javascript/helpers":8,"./assets/javascript/progressive-reveal":9,"./assets/javascript/validation":10,"./assets/javascript/vendor/details.polyfill":11}],13:[function(require,module,exports){
|
|
1417
1417
|
(function (global, factory) {
|
|
1418
1418
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
1419
1419
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
@@ -35627,7 +35627,7 @@ exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate :
|
|
|
35627
35627
|
/* eslint-disable */
|
|
35628
35628
|
'use strict'
|
|
35629
35629
|
|
|
35630
|
-
require('
|
|
35630
|
+
require('../../../frontend/themes/gov-uk/client-js');
|
|
35631
35631
|
|
|
35632
35632
|
var $ = require('jquery');
|
|
35633
35633
|
var typeahead = require('typeahead-aria');
|
|
@@ -35695,7 +35695,7 @@ $('.typeahead').each(function applyTypeahead() {
|
|
|
35695
35695
|
});
|
|
35696
35696
|
});
|
|
35697
35697
|
|
|
35698
|
-
},{"
|
|
35698
|
+
},{"../../../frontend/themes/gov-uk/client-js":3,"jquery":20,"typeahead-aria":23}],20:[function(require,module,exports){
|
|
35699
35699
|
arguments[4][15][0].apply(exports,arguments)
|
|
35700
35700
|
},{"dup":15}],21:[function(require,module,exports){
|
|
35701
35701
|
/*!
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
/package/frontend/toolkit/assets/{rebrand/images → images}/passports/new-window-link-blue.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/javascript → javascript}/vendor/details.polyfill.js
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/javascript → javascript}/vendor/indexof.polyfill.js
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/javascript → javascript}/vendor/safari-cachebuster.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_buttons.scss
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_details.scss
RENAMED
|
File without changes
|
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_forms.scss
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_helpers.scss
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_layout.scss
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_lists.scss
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_panels.scss
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_reset.scss
RENAMED
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/govuk-elements/_tables.scss
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_confirm-page.scss
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/frontend/toolkit/assets/{rebrand/stylesheets → stylesheets}/modules/_validation.scss
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|