Skip to content

Commit

Permalink
Merge pull request #102 from cabinetoffice/NTRNL-546-add-static-file-…
Browse files Browse the repository at this point in the history
…configuration-to-use-the-govuk-npm-directory

Ntrnl 546 add static file configuration to use the govuk npm directory
  • Loading branch information
Mouhajer-CO authored Aug 7, 2024
2 parents 6ae5e6b + 6c522e0 commit 3847f96
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 113 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ AUTH_SIGN_OUT_URL=${AUTH_PATH}/?logout=true
AWS_ACCESS_KEY_ID=DUMMYIDEXAMPLE
AWS_SECRET_ACCESS_KEY=DUMMYEXAMPLEKEY
BASE_URL=http://localhost:3000
CDN_HOST=test
CDN_HOST="d3ums2fp3imnyp.cloudfront.net"
COOKIE_ID_NAME=github-requests
COOKIE_PARSER_SECRET=test
COOKIE_SESSION_SECRET=test
Expand Down
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,13 @@ The issue is then reviewed by the team, and further comments may be requested if

### Running local development environment with Docker

Docker is used to run the application in **development** mode, with tooling setup to detect changes in local `src` directory and reload the container's node server.
Docker is used to run the application in **development** mode, with tooling setup to detect changes in local `src` directory and reload the container's node server.

- Ensure that `NODE_ENV=development` is set in the `.env` file.

- In order for static assets to be loaded, the `CDN_HOST` must be set to a CDN domain which serves the GOV.UK static assets.

### Building the application

To build the project, run:
To build the project, run:

```sh
make build
Expand Down
43 changes: 0 additions & 43 deletions assets/javascripts/cookies.js

This file was deleted.

7 changes: 5 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ const app = express();

app.disable('x-powered-by');

const assetsPath = path.join(__dirname, '../assets');
app.use('/assets', express.static(assetsPath));
const govukPath = path.join(__dirname, '../node_modules/govuk-frontend/dist/govuk');

app.use('/assets', express.static(`${govukPath}/assets`));
app.use('/govuk-frontend.min.css', express.static(`${govukPath}/govuk-frontend.min.css`));
app.use('/govuk-frontend.min.js', express.static(`${govukPath}/govuk-frontend.min.js`));

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
Expand Down
59 changes: 34 additions & 25 deletions src/config/helmet.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
import express from 'express';
import helmet from 'helmet';
import helmet, { HelmetOptions } from 'helmet';

import * as config from '../config';

export const configureHelmet = (app: express.Application) => {
app.use(helmet({
referrerPolicy: {
policy: 'strict-origin-when-cross-origin'
export const HELMET_OPTIONS: HelmetOptions = {
referrerPolicy: {
policy: 'strict-origin-when-cross-origin'
},
contentSecurityPolicy: {
useDefaults: true,
directives: {
defaultSrc: ["'self'"],
fontSrc: ["'self'", config.CDN_HOST],
styleSrc: [
"'self'",
"'unsafe-hashes'",
"'sha256-6FWIojjtZwiNizws7ImlHjGH3DA5yMh5x4c+/4UVpXk='",
config.CDN_HOST
],
scriptSrc: [
"'self'",
"'sha256-pOe+O2hOZnTvxPXzgAfiocCoHgEZxBBgg+a66TylmHw='",
"'sha256-GUQ5ad8JK5KmEWmROf3LZd9ge94daqNvd8xy9YS1iDw='",
"'sha256-rDMP7u4Lf+tIufrYmUZIhcf2T3WBD4Pweu0EXe+qaLA='",
"'sha256-wJphCpPdstup3Ojta3HnXJ3EOilATTTWg5oi4S9oi4s='",
config.CDN_HOST
],
imgSrc: ["'self'", 'data:', config.CDN_HOST],
connectSrc: ["'self'"],
formAction: ["'self'"],
objectSrc: ["'none'"]
},
contentSecurityPolicy: {
useDefaults: true,
directives: {
defaultSrc: ["'self'"],
fontSrc: ["'self'", config.CDN_HOST],
styleSrc: ["'self'", "'unsafe-hashes'", "'sha256-6FWIojjtZwiNizws7ImlHjGH3DA5yMh5x4c+/4UVpXk='", config.CDN_HOST],
scriptSrc: [
"'self'",
"'sha256-GUQ5ad8JK5KmEWmROf3LZd9ge94daqNvd8xy9YS1iDw='",
"'sha256-rDMP7u4Lf+tIufrYmUZIhcf2T3WBD4Pweu0EXe+qaLA='",
config.CDN_HOST
],
imgSrc: ["'self'", 'data:', config.CDN_HOST],
connectSrc: ["'self'"],
formAction: ["'self'"],
objectSrc: ["'none'"]
},
reportOnly: false
}
}));
reportOnly: false
}
};

export const configureHelmet = (app: express.Application) => {
app.use(helmet(HELMET_OPTIONS));
};
2 changes: 1 addition & 1 deletion src/config/nunjucks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const configureNunjucks = (app: express.Application, viewsPath: string) =
log.info(`Set nunjucks configurations and where nunjucks templates should resolve to: ${viewsPath}`);

const nunjucksEnv = nunjucks.configure(
[viewsPath, 'node_modules/govuk-frontend/dist', 'node_modules/govuk-frontend/dist/components'],
[viewsPath, 'node_modules/govuk-frontend/dist'],
{
autoescape: true,
express: app
Expand Down
13 changes: 6 additions & 7 deletions src/views/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
{% from "govuk/components/notification-banner/macro.njk" import govukNotificationBanner %}

{% block head %}
<link rel="stylesheet" type="text/css" media="all" href="//{{CDN_HOST}}/govuk-frontend/v5.3.0/govuk-frontend-5.3.0.min.css">
<link rel="stylesheet" type="text/css" media="all" href="/govuk-frontend.min.css">

<link rel="SHORTCUT ICON" href="//{{CDN_HOST}}/images/favicon.ico"/>
<link rel="icon" href="//{{CDN_HOST}}/images/favicon.ico" type="image/x-icon"/>
<link rel="SHORTCUT ICON" href="/assets/images/favicon.ico"/>
<link rel="icon" href="/assets/images/favicon.ico" type="image/x-icon"/>
{% endblock %}

{% block header %}
Expand Down Expand Up @@ -85,11 +85,10 @@

{% block bodyEnd %}
{% if FEATURE_FLAG_ENABLE_COOKIE_BANNER == "true" %}
<script src="/assets/javascripts/cookies.js"></script>
<script src="//{{CDN_HOST}}/app/github-requests-app/javascripts/cookies.js"></script>
{% endif %}
<script type="module" src="//{{CDN_HOST}}/govuk-frontend/v5.3.0/govuk-frontend-5.3.0.min.js"></script>
<script type="module">
import { initAll } from '//{{CDN_HOST}}/govuk-frontend/v5.3.0/govuk-frontend.min.js'
import { initAll } from '/govuk-frontend.min.js'
initAll()
</script>
{% endblock %}
{% endblock %}
25 changes: 0 additions & 25 deletions test/mock/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,31 +98,6 @@ export const MOCK_ERROR = {
message: 'Error message'
} as Error;

export const MOCK_HELMET_VALUE = {
referrerPolicy: {
policy: 'strict-origin-when-cross-origin'
},
contentSecurityPolicy: {
useDefaults: true,
directives: {
defaultSrc: ["'self'"],
fontSrc: ["'self'", config.CDN_HOST],
styleSrc: ["'self'", "'unsafe-hashes'", "'sha256-6FWIojjtZwiNizws7ImlHjGH3DA5yMh5x4c+/4UVpXk='", config.CDN_HOST],
scriptSrc: [
"'self'",
"'sha256-GUQ5ad8JK5KmEWmROf3LZd9ge94daqNvd8xy9YS1iDw='",
"'sha256-rDMP7u4Lf+tIufrYmUZIhcf2T3WBD4Pweu0EXe+qaLA='",
config.CDN_HOST
],
imgSrc: ["'self'", 'data:', config.CDN_HOST],
connectSrc: ["'self'"],
formAction: ["'self'"],
objectSrc: ["'none'"]
},
reportOnly: false
}
};

export const MOCK_RATE_LIMIT_VALUE = {
windowMs: 15 * 60 * 1000,
limit: 100,
Expand Down
6 changes: 3 additions & 3 deletions test/unit/config/helmet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ jest.mock('helmet');
import { describe, expect, test, jest, afterEach } from '@jest/globals';
import helmet from 'helmet';

import { configureHelmet } from '../../../src/config/helmet';
import { MOCK_HELMET_VALUE, MOCK_EXPRESS_APP } from '../../mock/data';
import { configureHelmet, HELMET_OPTIONS } from '../../../src/config/helmet';
import { MOCK_EXPRESS_APP } from '../../mock/data';

describe('Helmet Config test suites', () => {
afterEach(() => {
Expand All @@ -17,7 +17,7 @@ describe('Helmet Config test suites', () => {
configureHelmet(MOCK_EXPRESS_APP);

expect(mockHelmet).toHaveBeenCalledTimes(1);
expect(mockHelmet).toHaveBeenCalledWith(MOCK_HELMET_VALUE);
expect(mockHelmet).toHaveBeenCalledWith(HELMET_OPTIONS);
expect(MOCK_EXPRESS_APP.use).toHaveBeenCalled();
});
});
4 changes: 2 additions & 2 deletions test/unit/config/nunjucks.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
jest.mock('nunjucks');
jest.mock('../../../src/utils/logger');

import { describe, expect, test, jest } from '@jest/globals';
import { describe, expect, afterEach, test, jest } from '@jest/globals';

import * as nunjucks from 'nunjucks';

Expand Down Expand Up @@ -32,7 +32,7 @@ describe('Nunjucks Configuration test suites', () => {
configureNunjucks(MOCK_EXPRESS_APP, MOCK_VIEWS_PATH);

expect(nunjucks.configure).toHaveBeenCalledWith(
[MOCK_VIEWS_PATH, 'node_modules/govuk-frontend/dist', 'node_modules/govuk-frontend/dist/components'],
[MOCK_VIEWS_PATH, 'node_modules/govuk-frontend/dist'],
{
autoescape: true,
express: MOCK_EXPRESS_APP
Expand Down

0 comments on commit 3847f96

Please sign in to comment.