Skip to content
Snippets Groups Projects
Commit 8f35623c authored by Xiao Gui's avatar Xiao Gui
Browse files

bugfix: retry logic

chore: rework csp
breaking feat: plugin manifest no longer accept script
feat: logging malformed hash
parent 608aead8
No related branches found
No related tags found
No related merge requests found
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'
},
......
......@@ -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)
}
......
......@@ -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))
......
......@@ -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)
......
......@@ -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)
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment