diff --git a/deploy/csp/index.js b/deploy/csp/index.js index 4ce347a10fbce23d2d50acd0ed02f1f4a3e9f9db..b37e4a7cdcf37dc918007d2c0fa0e3cbd64c66a2 100644 --- a/deploy/csp/index.js +++ b/deploy/csp/index.js @@ -1,15 +1,22 @@ const csp = require('helmet-csp') const bodyParser = require('body-parser') -let ALLOWED_DEFAULT_SRC, DATA_SRC +let WHITE_LIST_SRC, DATA_SRC, SCRIPT_SRC const reportOnly = process.env.NODE_ENV !== 'production' try { - ALLOWED_DEFAULT_SRC = JSON.parse(process.env.ALLOWED_DEFAULT_SRC || '[]') + WHITE_LIST_SRC = JSON.parse(process.env.WHITE_LIST_SRC || '[]') } catch (e) { - console.warn(`parsing ALLOWED_DEFAULT_SRC error ${process.env.ALLOWED_DEFAULT_SRC}`, e) - ALLOWED_DEFAULT_SRC = [] + console.warn(`parsing WHITE_LIST_SRC error ${process.env.WHITE_LIST_SRC}`, e) + WHITE_LIST_SRC = [] +} + +try { + SCRIPT_SRC = JSON.parse(process.env.SCRIPT_SRC || '[]') +} catch (e) { + console.warn(`parsing SCRIPT_SRC error ${process.env.SCRIPT_SRC}`, e) + SCRIPT_SRC = [] } try { @@ -37,18 +44,24 @@ module.exports = (app) => { app.use(csp({ directives: { defaultSrc: [ - ...defaultAllowedSites + ...defaultAllowedSites, + ...WHITE_LIST_SRC ], styleSrc: [ ...defaultAllowedSites, '*.bootstrapcdn.com', '*.fontawesome.com', - "'unsafe-inline'" // required for angular [style.xxx] bindings + "'unsafe-inline'", // required for angular [style.xxx] bindings + ...WHITE_LIST_SRC + ], + fontSrc: [ + '*.fontawesome.com', + ...WHITE_LIST_SRC ], - fontSrc: [ '*.fontawesome.com' ], connectSrc: [ ...defaultAllowedSites, - ...dataSource + ...dataSource, + ...WHITE_LIST_SRC ], scriptSrc:[ "'self'", @@ -59,7 +72,8 @@ module.exports = (app) => { 'unpkg.com', '*.unpkg.com', '*.jsdelivr.net', - ...ALLOWED_DEFAULT_SRC + ...SCRIPT_SRC, + ...WHITE_LIST_SRC ], reportUri: '/report-violation' }, diff --git a/deploy/datasets/util.js b/deploy/datasets/util.js index f8378038f74495fe3e0f4f01d69191a85932cbcf..284d85f89b424538cb45741d467e84a957dd38d7 100644 --- a/deploy/datasets/util.js +++ b/deploy/datasets/util.js @@ -36,13 +36,15 @@ const init = async () => { const retry = (fn) => { let retryId - retryId = setInterval(() => { + retryId = setTimeout(() => { fn() .then(() => { console.log(`retry succeeded, clearing retryId`) clearTimeout(retryId) - }).catch(e => { + }) + .catch(e => { console.warn(`retry failed, retrying in 5sec`) + retry(fn) }) }, 5000) } diff --git a/src/atlasViewer/atlasViewer.pluginService.service.ts b/src/atlasViewer/atlasViewer.pluginService.service.ts index 1b2aedcdb5969832c9b7b6fe68ca6e15693bf649..850a1c90aec004499c8ffe2512364ad8be847c2b 100644 --- a/src/atlasViewer/atlasViewer.pluginService.service.ts +++ b/src/atlasViewer/atlasViewer.pluginService.service.ts @@ -117,18 +117,12 @@ export class PluginServices{ readyPlugin(plugin:PluginManifest):Promise<any>{ return Promise.all([ - isDefined(plugin.template) ? - Promise.resolve('template already provided') : - isDefined(plugin.templateURL) ? - this.fetch(plugin.templateURL, {responseType: 'text'}) - .then(template=>plugin.template = template) : - Promise.reject('both template and templateURL are not defined') , - isDefined(plugin.script) ? - Promise.resolve('script already provided') : - isDefined(plugin.scriptURL) ? - this.fetch(plugin.scriptURL, {responseType: 'text'}) - .then(script=>plugin.script = script) : - Promise.reject('both script and scriptURL are not defined') + isDefined(plugin.template) + ? Promise.resolve() + : isDefined(plugin.templateURL) + ? this.fetch(plugin.templateURL, {responseType: 'text'}).then(template=>plugin.template = template) + : Promise.reject('both template and templateURL are not defined') , + isDefined(plugin.scriptURL) ? Promise.resolve() : Promise.reject(`inline script has been deprecated. use scriptURL instead`) ]) } @@ -239,7 +233,8 @@ export class PluginServices{ } const script = document.createElement('script') - script.innerHTML = plugin.script + script.src = plugin.scriptURL + this.appendSrc(script) handler.onShutdown(() => this.removeSrc(script)) diff --git a/src/atlasViewer/atlasViewer.urlService.service.ts b/src/atlasViewer/atlasViewer.urlService.service.ts index a756f235b1cec42a20f7cbc2784eb2f8727eb300..ab2d36f759c6a595afb78cd4c2b0d896e7ccb2d6 100644 --- a/src/atlasViewer/atlasViewer.urlService.service.ts +++ b/src/atlasViewer/atlasViewer.urlService.service.ts @@ -179,6 +179,7 @@ export class AtlasViewerURLService{ /** * TODO poisonsed encoded char, send error message */ + this.uiService.showMessage(`cRegionSelectionParam is malformed: cannot decode ${n}`) return null } }).filter(v => !!v) diff --git a/src/plugin_examples/README.md b/src/plugin_examples/README.md index 2b1b126b3a0166eb2a416a5493705d5be63acd5e..c94e64a3d223507c0952d5115100b1c4d8f88ebc 100644 --- a/src/plugin_examples/README.md +++ b/src/plugin_examples/README.md @@ -6,7 +6,7 @@ A plugin needs to contain three files. - script JS -These files need to be served by GET requests over HTTP with appropriate CORS header. If your application requires a backend, it is strongly recommended to host these three files with your backend. +These files need to be served by GET requests over HTTP with appropriate CORS header. --- @@ -109,5 +109,5 @@ The script will always be appended **after** the rendering of the template. - for every observable subscription, call *unsubscribe()* in the *onShutdown* callback - some frameworks such as *jquery2*, *jquery3*, *react/reactdom* and *webcomponents* can be loaded via *interactiveViewer.pluinControl.loadExternalLibraries([LIBRARY_NAME_1, LIBRARY_NAME_2])*. if the libraries are loaded, remember to hook *interactiveViewer.pluginControl.unloadExternalLibraries([LIBRARY_NAME_1,LIBRARY_NAME_2])* in the *onShutdown* callback - when/if using webcomponents, please be aware that the `connectedCallback()` and `disconnectedCallback()` will be called everytime user toggle between *floating* and *docked* modes. -- when user navigate to a new template all existing widgets will be destroyed, unless the `persistency` is set to `true` in `mannifest.json`. +- when user navigate to a new template all existing widgets will be destroyed, unless the `persistency` is set to `true` in `manifest.json`. - for a list of APIs, see [plugin_api.md](plugin_api.md)