From 9cd1cfddbcee7a5649073a23dd37413025c6698b Mon Sep 17 00:00:00 2001 From: CamClendenon Date: Tue, 29 Apr 2025 21:28:30 -0700 Subject: [PATCH 01/15] Added Documentation and pushing the initial CSP tag as well. --- src/client/index.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/client/index.html b/src/client/index.html index b50f49007c..892955c214 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -13,6 +13,24 @@ Open Energy Dashboard + + + From 8cdc2da7b951fade24ead083238237b95022116e Mon Sep 17 00:00:00 2001 From: CamClendenon Date: Thu, 1 May 2025 07:52:57 -0700 Subject: [PATCH 02/15] Updates to documentation based on Steve's reccomendation --- src/client/index.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/client/index.html b/src/client/index.html index 892955c214..d89b883945 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -14,14 +14,16 @@ - From 956e878e0f2c5479e467540a60347ee418ab5d2b Mon Sep 17 00:00:00 2001 From: CamClendenon Date: Thu, 1 May 2025 08:08:29 -0700 Subject: [PATCH 03/15] Grammar correction --- src/client/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/index.html b/src/client/index.html index d89b883945..b91de7a5e9 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -22,7 +22,7 @@ To test CSP rules change http-equiv=”Content-Security-Policy” to http-equiv=”Content-Security-Policy-Report-Only” this allows us to send reports of what would have been blocked without actually blocking it. - For sites use OED and are blocked by these CSP rules may add their site to the exception they may list their website link next to the tag that is blocking + For sites using OED and are blocked by these CSP rules may add their site to the exception they may list their website link next to the tag that is blocking the user site. The site link must be added after 'self' but before the semi colon marking the end of that tag. The font-src tag is a great example on how to implement a site to the exception list. Another example for adding a site (https://newException.com) to a tag with multiple sites as an exceptions would be : img-src 'self' http://example.com https://site_example.net; becomes img-src 'self' http://example.com https://site_example.net https://newException.com; From fc1eb21225648e8411ca21595276e7db900b30a4 Mon Sep 17 00:00:00 2001 From: CamClendenon Date: Fri, 2 May 2025 21:26:24 -0700 Subject: [PATCH 04/15] Current Attempt to Mend CSP rule (STILL IN PROGRESS) --- src/client/app/index.tsx | 8 +++++++- src/client/index.html | 37 ++++++++++++++++++++++++++++++------- src/server/app.js | 8 ++++++++ webpack.config.js | 24 +++++++++++++++++++++--- 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/client/app/index.tsx b/src/client/app/index.tsx index 83dfee7ad8..407c4fe0d7 100644 --- a/src/client/app/index.tsx +++ b/src/client/app/index.tsx @@ -1,7 +1,13 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - +// if (typeof document !== 'undefined') { +// const script = document.querySelector('script[nonce]'); +// if (script && script.nonce) { +// (window as any).webpackNonce = script.nonce; +// console.log("webpackNonce set to", script.nonce); +// } +// } import 'bootstrap/dist/css/bootstrap.css'; import * as React from 'react'; import { createRoot } from 'react-dom/client'; diff --git a/src/client/index.html b/src/client/index.html index b91de7a5e9..1a87475951 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -14,6 +14,7 @@ + - + + + + +
- + + + diff --git a/src/server/app.js b/src/server/app.js index c954d7f772..e04a6e9df7 100644 --- a/src/server/app.js +++ b/src/server/app.js @@ -33,6 +33,8 @@ const units = require('./routes/units'); const conversions = require('./routes/conversions'); const ciks = require('./routes/ciks'); +const crypto = require('node:crypto') + // Limit the rate of overall requests to OED // Note that the rate limit may make the automatic test return the value of 429. In that case, the limiters below need to be increased. // TODO Verify that user see the message returned, see https://express-rate-limit.mintlify.app/reference/configuration#message @@ -145,6 +147,12 @@ router.get('*', (req, res) => { fs.readFile(path.resolve(__dirname, '..', 'client', 'index.html'), (err, html) => { const subdir = config.subdir || '/'; let htmlPlusData = html.toString().replace('SUBDIR', subdir); + + const nonce = crypto.randomBytes(16).toString('base64url') + htmlPlusData = htmlPlusData.replace(/__NONCE__/g, nonce) + + res.setHeader('Content-Security-Policy', `default-src 'self'; img-src 'self' data: ; font-src 'self' https://maxcdn.bootstrapcdn.com; media-src 'self'; script-src 'self' ; style-src 'self' https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css 'unsafe-inline'; style-src-elem 'unsafe-inline' https://maxcdn.bootstrapcdn.com;`) + res.send(htmlPlusData); }); }); diff --git a/webpack.config.js b/webpack.config.js index 8ff0f7d647..7f22dca767 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -38,11 +38,29 @@ const config = { module: { rules: [ // All TypeScript ('.ts' or '.tsx') will be handled by 'awesome-typescript-loader'. - { test: /\.[jt]sx?$/, exclude: /node_modules/, use: 'ts-loader' }, + { test: /\.[jt]sx?$/, exclude: /node_modules/, use: 'ts-loader' + // , + // options: { + // attributes: { + // nonce: 'webpackTSNonce' + // }} + }, // CSS stylesheet loader. { test: /\.css$/, use: [ - {loader: 'style-loader'}, - {loader: 'css-loader'} + {loader: 'style-loader' + // , + // options: { + // attributes: { + // nonce: 'webpackNonce' + // }} + }, + {loader: 'css-loader' + // , + // options: { + // attributes: { + // nonce: 'webpackCSSNonce' + // }} + } ] }, // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. { enforce: 'pre', test: /\.js$/, use:[{loader: 'source-map-loader'}] } From 5824620bbcb9e7f8871fa49362255408b80d67c4 Mon Sep 17 00:00:00 2001 From: CamClendenon Date: Sat, 3 May 2025 14:16:25 -0700 Subject: [PATCH 05/15] Semi Working Page with CSP rule, Still csp blocking some things --- src/client/app/index.tsx | 18 +++++++++------- src/client/index.html | 45 ++++++++++++++++++++++------------------ src/server/app.js | 2 +- webpack.config.js | 29 +++++++------------------- 4 files changed, 45 insertions(+), 49 deletions(-) diff --git a/src/client/app/index.tsx b/src/client/app/index.tsx index 407c4fe0d7..fd557ee67a 100644 --- a/src/client/app/index.tsx +++ b/src/client/app/index.tsx @@ -1,14 +1,18 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// if (typeof document !== 'undefined') { -// const script = document.querySelector('script[nonce]'); -// if (script && script.nonce) { -// (window as any).webpackNonce = script.nonce; -// console.log("webpackNonce set to", script.nonce); -// } -// } + + const originalAppendChild = document.head.appendChild; + +document.head.appendChild = function(node) { + if (node.tagName === 'STYLE' && !node.nonce) { + node.setAttribute('nonce', window.__plotly_nonce__ || window.__webpack_nonce__); + } + return originalAppendChild.call(this, node); +}; + import 'bootstrap/dist/css/bootstrap.css'; +console.log('BootstrapCSS Loaded'); import * as React from 'react'; import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; diff --git a/src/client/index.html b/src/client/index.html index 1a87475951..8ff4067350 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -8,11 +8,18 @@ + Open Energy Dashboard - + + + + img-src 'self' http://example.com https://site_example.net; becomes img-src 'self' http://example.com https://site_example.net https://newException.com; + --> - + default-src 'self'; + img-src 'self'; + font-src 'self' https://maxcdn.bootstrapcdn.com; + media-src 'self'; + script-src 'self' 'nonce-__NONCE__'; + style-src 'self' 'nonce-__NONCE__'; "> --> + + -->
- - - + diff --git a/src/server/app.js b/src/server/app.js index e04a6e9df7..800ed25d63 100644 --- a/src/server/app.js +++ b/src/server/app.js @@ -151,7 +151,7 @@ router.get('*', (req, res) => { const nonce = crypto.randomBytes(16).toString('base64url') htmlPlusData = htmlPlusData.replace(/__NONCE__/g, nonce) - res.setHeader('Content-Security-Policy', `default-src 'self'; img-src 'self' data: ; font-src 'self' https://maxcdn.bootstrapcdn.com; media-src 'self'; script-src 'self' ; style-src 'self' https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css 'unsafe-inline'; style-src-elem 'unsafe-inline' https://maxcdn.bootstrapcdn.com;`) + res.setHeader('Content-Security-Policy-Report-Only', `default-src 'self'; img-src 'self'; font-src 'self' https://maxcdn.bootstrapcdn.com 'nonce-${nonce}'; media-src 'self'; script-src 'self' 'nonce-${nonce}' ; style-src 'self' 'nonce-${nonce}';`) res.send(htmlPlusData); }); diff --git a/webpack.config.js b/webpack.config.js index 7f22dca767..123dde4d4a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,7 +4,7 @@ const LodashModuleReplacementPlugin = require('lodash-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); -const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin'); const webpack = require('webpack'); const path = require('path'); @@ -38,29 +38,16 @@ const config = { module: { rules: [ // All TypeScript ('.ts' or '.tsx') will be handled by 'awesome-typescript-loader'. - { test: /\.[jt]sx?$/, exclude: /node_modules/, use: 'ts-loader' - // , - // options: { - // attributes: { - // nonce: 'webpackTSNonce' - // }} - }, + { test: /\.[jt]sx?$/, exclude: /node_modules/, use: 'ts-loader'}, // CSS stylesheet loader. { test: /\.css$/, use: [ - {loader: 'style-loader' - // , - // options: { - // attributes: { - // nonce: 'webpackNonce' - // }} + {loader: 'style-loader', + options: { + attributes: { + nonce: '__webpack_nonce__' + }} }, - {loader: 'css-loader' - // , - // options: { - // attributes: { - // nonce: 'webpackCSSNonce' - // }} - } + {loader: 'css-loader'} ] }, // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. { enforce: 'pre', test: /\.js$/, use:[{loader: 'source-map-loader'}] } From d45135df4fb51dacd413d9a3c0ca68965267c0b7 Mon Sep 17 00:00:00 2001 From: CamClendenon Date: Sun, 4 May 2025 18:06:04 -0700 Subject: [PATCH 06/15] Added new file to add Emotion/Cache which helps let the nonce be saved to any emotion based styles. Fixed majority of the CSP style tag problems but a few still remain. (Still in Progress) --- src/client/app/emotionCache.ts | 10 ++++++ src/client/app/index.tsx | 63 +++++++++++++++++++++++++++++----- src/client/index.html | 18 ++++------ src/server/app.js | 4 +-- webpack.config.js | 3 +- 5 files changed, 74 insertions(+), 24 deletions(-) create mode 100644 src/client/app/emotionCache.ts diff --git a/src/client/app/emotionCache.ts b/src/client/app/emotionCache.ts new file mode 100644 index 0000000000..332a4df159 --- /dev/null +++ b/src/client/app/emotionCache.ts @@ -0,0 +1,10 @@ +import createCache from '@emotion/cache'; + +const nonce = (document.querySelector('script[nonce]') as HTMLScriptElement | null)?.nonce; + +const emotionCache = createCache({ + key: 'css', + nonce: nonce, +}); + +export default emotionCache; \ No newline at end of file diff --git a/src/client/app/index.tsx b/src/client/app/index.tsx index fd557ee67a..543d0511f2 100644 --- a/src/client/app/index.tsx +++ b/src/client/app/index.tsx @@ -1,18 +1,59 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +const __webpack_nonce__ = (document.querySelector('script[nonce]') as HTMLScriptElement | null)?.nonce; +(window as any).__webpack_nonce__ = __webpack_nonce__; +(window as any).__plotly_nonce__ = __webpack_nonce__; - const originalAppendChild = document.head.appendChild; +console.log('Set __webpack_nonce__ to:', __webpack_nonce__); -document.head.appendChild = function(node) { - if (node.tagName === 'STYLE' && !node.nonce) { - node.setAttribute('nonce', window.__plotly_nonce__ || window.__webpack_nonce__); - } - return originalAppendChild.call(this, node); +console.log('Set nonces:', __webpack_nonce__); +declare global { + interface Window { + __webpack_nonce__?: string; + __plotly_nonce__?: string; + } +} + + +const originalAppendChild = document.head.appendChild; +document.head.appendChild = function (node: any) { + if ( + node instanceof HTMLStyleElement + ) { + console.log('Appending style, has nonce:', __webpack_nonce__); + node.setAttribute('nonce',__webpack_nonce__|| ''); + } + + try { + return originalAppendChild.call(this, node); + } catch (err) { + console.error('Failed to append style:', err); + throw err; + } }; +// document.head.appendChild = function (node: any) { +// if (node instanceof HTMLStyleElement) { +// const hasNonce = node.getAttribute('nonce'); +// console.log('Appending style, has nonce:', hasNonce); +// if (!hasNonce) { +// const nonceToUse = window.__plotly_nonce__ || window.__webpack_nonce__ || ''; +// console.log('Setting nonce on style element:', nonceToUse); +// node.setAttribute('nonce', nonceToUse); +// } +// } +// try { +// return originalAppendChild.call(this, node); +// } catch (err) { +// console.error('Failed to append style:', err, node); +// throw err; +// } +// }; +console.log('Before import, __webpack_nonce__ =', __webpack_nonce__); import 'bootstrap/dist/css/bootstrap.css'; console.log('BootstrapCSS Loaded'); +console.log('After import, __webpack_nonce__ =', __webpack_nonce__); import * as React from 'react'; import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; @@ -23,13 +64,17 @@ import './styles/index.css'; store.dispatch(initApp()); +import { CacheProvider } from '@emotion/react'; +import emotionCache from './emotionCache'; // Renders the entire application, starting with RouteComponent, into the root div const container = document.getElementById('root') as HTMLElement; const root = createRoot(container); root.render( // Provides the Redux store to all child components - < Provider store={store} stabilityCheck='always' > - < RouteComponent /> - + + + + + ); diff --git a/src/client/index.html b/src/client/index.html index 8ff4067350..7af1179f41 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -8,10 +8,10 @@ - @@ -19,7 +19,7 @@ - + - - - - - + + + + + Open Energy Dashboard + + + + + + + + -
+
+ + - + From f4c3206b4aa6154c3f734c250c1b2ab0c4ce5395 Mon Sep 17 00:00:00 2001 From: Steven Huss-Lederman Date: Mon, 1 Dec 2025 13:54:38 -0600 Subject: [PATCH 08/15] Add MPL & formatting --- src/client/app/emotionCache.ts | 8 ++++++-- src/client/app/index.tsx | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/client/app/emotionCache.ts b/src/client/app/emotionCache.ts index 332a4df159..7c8bf1d056 100644 --- a/src/client/app/emotionCache.ts +++ b/src/client/app/emotionCache.ts @@ -1,10 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + import createCache from '@emotion/cache'; const nonce = (document.querySelector('script[nonce]') as HTMLScriptElement | null)?.nonce; const emotionCache = createCache({ key: 'css', - nonce: nonce, + nonce: nonce }); -export default emotionCache; \ No newline at end of file +export default emotionCache; diff --git a/src/client/app/index.tsx b/src/client/app/index.tsx index 543d0511f2..7b87b772dd 100644 --- a/src/client/app/index.tsx +++ b/src/client/app/index.tsx @@ -1,6 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + const __webpack_nonce__ = (document.querySelector('script[nonce]') as HTMLScriptElement | null)?.nonce; (window as any).__webpack_nonce__ = __webpack_nonce__; (window as any).__plotly_nonce__ = __webpack_nonce__; @@ -22,7 +23,7 @@ document.head.appendChild = function (node: any) { node instanceof HTMLStyleElement ) { console.log('Appending style, has nonce:', __webpack_nonce__); - node.setAttribute('nonce',__webpack_nonce__|| ''); + node.setAttribute('nonce', __webpack_nonce__ || ''); } try { From 33aa0a596b02888e81144cfedefe1163e5c3cfaa Mon Sep 17 00:00:00 2001 From: Steven Huss-Lederman Date: Mon, 1 Dec 2025 14:30:29 -0600 Subject: [PATCH 09/15] spelling fix --- src/client/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/index.html b/src/client/index.html index 65dd41d37b..18d9a7db27 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -30,7 +30,7 @@ what would have been blocked without actually blocking it. For sites using OED and are blocked by these CSP rules may add their site to the exception they may list their website link next to the tag that is blocking - the user site. The site link must be added after 'self' but before the semi colon marking the end of that tag. The font-src tag is a great example on how to implement + the user site. The site link must be added after 'self' but before the semicolon marking the end of that tag. The font-src tag is a great example on how to implement a site to the exception list. Another example for adding a site (https://newException.com) to a tag with multiple sites as an exceptions would be : img-src 'self' http://example.com https://site_example.net; becomes img-src 'self' http://example.com https://site_example.net https://newException.com; --> From 88d9f402fdbd10da04fce6658704611484e95b98 Mon Sep 17 00:00:00 2001 From: Brian Raymond Date: Thu, 15 Jan 2026 15:46:32 +0000 Subject: [PATCH 10/15] Updated changes in PR 1484 with improved formatting, comments, and readability. --- src/client/app/index.tsx | 25 ++----------------------- src/client/index.html | 21 +++++++++++---------- src/server/app.js | 1 + 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/client/app/index.tsx b/src/client/app/index.tsx index 7b87b772dd..135f9ce774 100644 --- a/src/client/app/index.tsx +++ b/src/client/app/index.tsx @@ -2,13 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// Creates the Webpack nonce from the main nonce, which allows webpack to apply the CSP to its scripts const __webpack_nonce__ = (document.querySelector('script[nonce]') as HTMLScriptElement | null)?.nonce; (window as any).__webpack_nonce__ = __webpack_nonce__; (window as any).__plotly_nonce__ = __webpack_nonce__; -console.log('Set __webpack_nonce__ to:', __webpack_nonce__); - -console.log('Set nonces:', __webpack_nonce__); declare global { interface Window { __webpack_nonce__?: string; @@ -33,28 +31,9 @@ document.head.appendChild = function (node: any) { throw err; } }; -// document.head.appendChild = function (node: any) { -// if (node instanceof HTMLStyleElement) { -// const hasNonce = node.getAttribute('nonce'); -// console.log('Appending style, has nonce:', hasNonce); -// if (!hasNonce) { -// const nonceToUse = window.__plotly_nonce__ || window.__webpack_nonce__ || ''; -// console.log('Setting nonce on style element:', nonceToUse); -// node.setAttribute('nonce', nonceToUse); -// } -// } -// try { -// return originalAppendChild.call(this, node); -// } catch (err) { -// console.error('Failed to append style:', err, node); -// throw err; -// } -// }; -console.log('Before import, __webpack_nonce__ =', __webpack_nonce__); + import 'bootstrap/dist/css/bootstrap.css'; -console.log('BootstrapCSS Loaded'); -console.log('After import, __webpack_nonce__ =', __webpack_nonce__); import * as React from 'react'; import { createRoot } from 'react-dom/client'; import { Provider } from 'react-redux'; diff --git a/src/client/index.html b/src/client/index.html index 18d9a7db27..0a68b6f6f5 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -22,17 +22,18 @@ nonce="{{nonce}}"> - - - - + diff --git a/src/server/app.js b/src/server/app.js index f721663c74..4d89a19979 100644 --- a/src/server/app.js +++ b/src/server/app.js @@ -148,6 +148,7 @@ router.get('*', (req, res) => { const subdir = config.subdir || '/'; let htmlPlusData = html.toString().replace('SUBDIR', subdir); + //assigns a value to the nonce in order to check for authenticity const nonce = crypto.randomBytes(16).toString('base64url') htmlPlusData = htmlPlusData.replace(/{{nonce}}/g, nonce) diff --git a/webpack.config.js b/webpack.config.js index c10128d555..6e47ced240 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -44,6 +44,7 @@ const config = { {loader: 'style-loader', options: { attributes: { + //this line allows the webpack nonce to be applied to styles nonce: '__webpack_nonce__' } } From 28c2cd92e25294cb07922039fdcc71bf1785d290 Mon Sep 17 00:00:00 2001 From: Brian Raymond Date: Thu, 12 Feb 2026 22:04:51 +0000 Subject: [PATCH 12/15] Improved the formatting to align with OED's standards. --- src/client/app/emotionCache.ts | 3 +-- src/client/app/index.tsx | 25 +++++++++++++------------ src/server/app.js | 7 +++---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/client/app/emotionCache.ts b/src/client/app/emotionCache.ts index d5f9847337..b32ec48569 100644 --- a/src/client/app/emotionCache.ts +++ b/src/client/app/emotionCache.ts @@ -1,8 +1,7 @@ -//imports the createSche function from React's Emotion library import createCache from '@emotion/cache'; //creates the nonce for the script being run -//he nonce works alongside the webpack_nonce and plotly_nonce to protect against unwated scripts +//the nonce works alongside the webpack_nonce and plotly_nonce to protect against unwanted scripts const nonce = (document.querySelector('script[nonce]') as HTMLScriptElement | null)?.nonce; const emotionCache = createCache({ diff --git a/src/client/app/index.tsx b/src/client/app/index.tsx index f647e8bcf1..49c5f4d002 100644 --- a/src/client/app/index.tsx +++ b/src/client/app/index.tsx @@ -1,9 +1,20 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import 'bootstrap/dist/css/bootstrap.css'; +import * as React from 'react'; +import { createRoot } from 'react-dom/client'; +import { Provider } from 'react-redux'; +import { store } from './store'; +import RouteComponent from './components/RouteComponent'; +import { initApp } from './redux/slices/appStateSlice'; +import './styles/index.css'; +import { CacheProvider } from '@emotion/react'; +import emotionCache from './emotionCache'; - //these lines take the nonce, and create the webpack and plotly nonces from it - //these are additional nonces that contribute to styling with webpacvk and plotly +//these lines take the nonce, and create the webpack and plotly nonces from it +//these are additional nonces that contribute to styling with webpack and plotly const __webpack_nonce__ = (document.querySelector('script[nonce]') as HTMLScriptElement | null)?.nonce; (window as any).__webpack_nonce__ = __webpack_nonce__; (window as any).__plotly_nonce__ = __webpack_nonce__; @@ -31,19 +42,9 @@ document.head.appendChild = function (node: any) { throw err; } }; -import 'bootstrap/dist/css/bootstrap.css'; -import * as React from 'react'; -import { createRoot } from 'react-dom/client'; -import { Provider } from 'react-redux'; -import { store } from './store'; -import RouteComponent from './components/RouteComponent'; -import { initApp } from './redux/slices/appStateSlice'; -import './styles/index.css'; store.dispatch(initApp()); -import { CacheProvider } from '@emotion/react'; -import emotionCache from './emotionCache'; // Renders the entire application, starting with RouteComponent, into the root div const container = document.getElementById('root') as HTMLElement; const root = createRoot(container); diff --git a/src/server/app.js b/src/server/app.js index 4d89a19979..d608e5d1d9 100644 --- a/src/server/app.js +++ b/src/server/app.js @@ -32,8 +32,7 @@ const conversionArray = require('./routes/conversionArray'); const units = require('./routes/units'); const conversions = require('./routes/conversions'); const ciks = require('./routes/ciks'); - -const crypto = require('node:crypto') +const crypto = require('node:crypto'); // Limit the rate of overall requests to OED // Note that the rate limit may make the automatic test return the value of 429. In that case, the limiters below need to be increased. @@ -149,8 +148,8 @@ router.get('*', (req, res) => { let htmlPlusData = html.toString().replace('SUBDIR', subdir); //assigns a value to the nonce in order to check for authenticity - const nonce = crypto.randomBytes(16).toString('base64url') - htmlPlusData = htmlPlusData.replace(/{{nonce}}/g, nonce) + const nonce = crypto.randomBytes(16).toString('base64url'); + htmlPlusData = htmlPlusData.replace(/{{nonce}}/g, nonce); res.setHeader('Content-Security-Policy', `default-src 'self'; img-src 'self' data: ; font-src 'self' https://maxcdn.bootstrapcdn.com ; media-src 'self'; script-src 'self' 'nonce-${nonce}' ; style-src 'self' 'nonce-${nonce}' 'unsafe-inline';`) From 282260cfa6891e125df618500bbd0044adb5bf7f Mon Sep 17 00:00:00 2001 From: Steven Huss-Lederman Date: Fri, 12 Jun 2026 10:33:10 -0500 Subject: [PATCH 13/15] formatting per comments --- src/client/index.html | 25 ++++++++++++------------- webpack.config.js | 27 +++++++++++++++------------ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/client/index.html b/src/client/index.html index 3f7394d652..c4b8d0dfc8 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -17,11 +17,10 @@ Open Energy Dashboard - - - - - + + +