diff --git a/client/components/admin/admin-general.vue b/client/components/admin/admin-general.vue index 52b90005..400dcc80 100644 --- a/client/components/admin/admin-general.vue +++ b/client/components/admin/admin-general.vue @@ -184,6 +184,16 @@ hint='Should be enabled when using a reverse-proxy like nginx, apache, CloudFlare, etc in front of Wiki.js. Turn off otherwise.' ) + v-divider.mt-3 + v-switch( + inset + label='Subresource Integrity' + color='red darken-2' + v-model='config.securitySRI' + persistent-hint + hint='This ensure that resources such as CSS and JS files are not altered during delivery.' + ) + v-divider.mt-3 v-switch( inset @@ -262,6 +272,7 @@ export default { securityIframe: true, securityReferrerPolicy: true, securityTrustProxy: true, + securitySRI: true, securityHSTS: false, securityHSTSDuration: 0, securityCSP: false, @@ -309,6 +320,7 @@ export default { securityIframe: _.get(this.config, 'securityIframe', false), securityReferrerPolicy: _.get(this.config, 'securityReferrerPolicy', false), securityTrustProxy: _.get(this.config, 'securityTrustProxy', false), + securitySRI: _.get(this.config, 'securitySRI', false), securityHSTS: _.get(this.config, 'securityHSTS', false), securityHSTSDuration: _.get(this.config, 'securityHSTSDuration', 0), securityCSP: _.get(this.config, 'securityCSP', false), diff --git a/client/components/common/page-selector.vue b/client/components/common/page-selector.vue index 4473881b..7db9c8c5 100644 --- a/client/components/common/page-selector.vue +++ b/client/components/common/page-selector.vue @@ -17,7 +17,7 @@ v-toolbar(color='grey darken-3', dark, dense, flat) .body-2 Virtual Folders v-spacer - v-btn(icon, tile) + v-btn(icon, tile, href='https://docs.requarks.io/', target='_blank') v-icon mdi-help-box v-treeview( :active.sync='currentNode' @@ -37,8 +37,8 @@ v-toolbar(color='blue darken-2', dark, dense, flat) .body-2 Pages v-spacer - v-btn(icon, tile): v-icon mdi-content-save-move-outline - v-btn(icon, tile): v-icon mdi-trash-can-outline + v-btn(icon, tile, disabled): v-icon mdi-content-save-move-outline + v-btn(icon, tile, disabled): v-icon mdi-trash-can-outline v-list.py-0(dense, v-if='currentPages.length > 0') v-list-item-group( v-model='currentPage' @@ -131,6 +131,7 @@ export default { children: [] }], pages: [], + all: [], namespaces: siteLangs.length ? siteLangs.map(ns => ns.code) : [siteConfig.lang] } }, @@ -162,6 +163,20 @@ export default { this.$nextTick(() => { this.currentNode = oldValue }) + } else { + if (this.openNodes.indexOf(newValue[0]) < 0) { // auto open and load children + const current = _.find(this.all, ['id', newValue[0]]) + if (current) { + if (this.openNodes.indexOf(current.parent) < 0) { + this.$nextTick(() => { + this.openNodes.push(current.parent) + }) + } + } + this.$nextTick(() => { + this.openNodes.push(newValue[0]) + }) + } } }, currentPage (newValue, oldValue) { @@ -204,6 +219,8 @@ export default { } this.pages.push(...itemPages) + this.all.push(...items) + this.searchLoading = false } } diff --git a/client/graph/admin/site/site-query-config.gql b/client/graph/admin/site/site-query-config.gql index 5af45d09..d8cca6d8 100644 --- a/client/graph/admin/site/site-query-config.gql +++ b/client/graph/admin/site/site-query-config.gql @@ -16,6 +16,7 @@ securityIframe securityReferrerPolicy securityTrustProxy + securitySRI securityHSTS securityHSTSDuration securityCSP diff --git a/dev/templates/legacy.pug b/dev/templates/legacy.pug index 6c72a55e..4e7b7414 100644 --- a/dev/templates/legacy.pug +++ b/dev/templates/legacy.pug @@ -43,21 +43,11 @@ html //- CSS <% for (var index in htmlWebpackPlugin.files.css) { %> - <% if (htmlWebpackPlugin.files.cssIntegrity) { %> - link( - type='text/css' - rel='stylesheet' - href='<%= htmlWebpackPlugin.files.css[index] %>' - integrity='<%= htmlWebpackPlugin.files.cssIntegrity[index] %>' - crossorigin='<%= webpackConfig.output.crossOriginLoading %>' - ) - <% } else { %> link( type='text/css' rel='stylesheet' href='<%= htmlWebpackPlugin.files.css[index] %>' ) - <% } %> <% } %> script( @@ -67,19 +57,10 @@ html //- JS <% for (var index in htmlWebpackPlugin.files.js) { %> - <% if (htmlWebpackPlugin.files.cssIntegrity) { %> - script( - type='text/javascript' - src='<%= htmlWebpackPlugin.files.js[index] %>' - integrity='<%= htmlWebpackPlugin.files.jsIntegrity[index] %>' - crossorigin='<%= webpackConfig.output.crossOriginLoading %>' - ) - <% } else { %> script( type='text/javascript' src='<%= htmlWebpackPlugin.files.js[index] %>' ) - <% } %> <% } %> != analyticsCode.head diff --git a/dev/templates/master.pug b/dev/templates/master.pug index 82a48406..0f4cabd0 100644 --- a/dev/templates/master.pug +++ b/dev/templates/master.pug @@ -52,7 +52,7 @@ html(lang=siteConfig.lang) type='text/css' rel='stylesheet' href='<%= htmlWebpackPlugin.files.css[index] %>' - integrity='<%= htmlWebpackPlugin.files.cssIntegrity[index] %>' + integrity=config.security.securitySRI ? '<%= htmlWebpackPlugin.files.cssIntegrity[index] %>' : false crossorigin='<%= webpackConfig.output.crossOriginLoading %>' ) <% } else { %> @@ -66,11 +66,11 @@ html(lang=siteConfig.lang) //- JS <% for (var index in htmlWebpackPlugin.files.js) { %> - <% if (htmlWebpackPlugin.files.cssIntegrity) { %> + <% if (htmlWebpackPlugin.files.jsIntegrity) { %> script( type='text/javascript' src='<%= htmlWebpackPlugin.files.js[index] %>' - integrity='<%= htmlWebpackPlugin.files.jsIntegrity[index] %>' + integrity=config.security.securitySRI ? '<%= htmlWebpackPlugin.files.jsIntegrity[index] %>' : false crossorigin='<%= webpackConfig.output.crossOriginLoading %>' ) <% } else { %> diff --git a/package.json b/package.json index ce5af2fc..cd64fba7 100644 --- a/package.json +++ b/package.json @@ -35,22 +35,22 @@ }, "dependencies": { "@aoberoi/passport-slack": "1.0.5", - "@bugsnag/js": "6.4.1", + "@bugsnag/js": "6.4.2", "@exlinc/keycloak-passport": "1.0.2", - "algoliasearch": "3.35.0", + "algoliasearch": "3.35.1", "apollo-fetch": "0.7.0", - "apollo-server": "2.9.4", - "apollo-server-express": "2.9.4", + "apollo-server": "2.9.6", + "apollo-server-express": "2.9.6", "auto-load": "3.0.4", - "aws-sdk": "2.538.0", + "aws-sdk": "2.548.0", "azure-search-client": "3.1.5", "bcryptjs-then": "1.0.1", - "bluebird": "3.5.5", + "bluebird": "3.7.0", "body-parser": "1.19.0", "brute-knex": "4.0.0", "chalk": "2.4.2", "cheerio": "1.0.0-rc.3", - "chokidar": "3.1.1", + "chokidar": "3.2.1", "clean-css": "4.2.1", "compression": "1.7.4", "connect-session-knex": "1.4.0", @@ -59,35 +59,35 @@ "custom-error-instance": "2.1.1", "dependency-graph": "0.8.0", "diff": "4.0.1", - "diff2html": "2.11.3", + "diff2html": "2.12.1", "dotize": "0.3.0", "elasticsearch6": "npm:@elastic/elasticsearch@6", "elasticsearch7": "npm:@elastic/elasticsearch@7", "emoji-regex": "8.0.0", "express": "4.17.1", "express-brute": "1.0.1", - "express-session": "1.16.2", + "express-session": "1.17.0", "file-type": "12.3.0", - "filesize": "4.2.1", + "filesize": "5.0.3", "fs-extra": "8.1.0", "getos": "3.1.1", "graphql": "14.5.8", "graphql-list-fields": "2.0.2", - "graphql-rate-limit-directive": "1.1.0", + "graphql-rate-limit-directive": "1.2.0", "graphql-subscriptions": "1.1.0", "graphql-tools": "4.0.5", "he": "1.2.0", "highlight.js": "9.15.10", - "i18next": "17.0.16", + "i18next": "17.2.0", "i18next-express-middleware": "1.8.2", "i18next-node-fs-backend": "2.1.3", - "image-size": "0.8.2", + "image-size": "0.8.3", "js-base64": "2.5.1", "js-binary": "1.2.0", "js-yaml": "3.13.1", "jsonwebtoken": "8.5.1", "klaw": "3.0.0", - "knex": "0.19.4", + "knex": "0.19.5", "lodash": "4.17.15", "markdown-it": "10.0.0", "markdown-it-abbr": "1.0.4", @@ -111,10 +111,10 @@ "mssql": "5.1.0", "multer": "1.4.2", "mysql2": "1.7.0", - "nanoid": "2.1.1", + "nanoid": "2.1.3", "node-2fa": "1.1.2", "node-cache": "4.2.1", - "nodemailer": "6.3.0", + "nodemailer": "6.3.1", "objection": "1.6.11", "passport": "0.4.0", "passport-auth0": "1.2.1", @@ -148,7 +148,7 @@ "request-promise": "4.2.4", "safe-regex": "2.0.2", "sanitize-filename": "1.6.3", - "scim-query-filter-parser": "2.0.0", + "scim-query-filter-parser": "2.0.1", "semver": "6.3.0", "serve-favicon": "2.5.0", "simple-git": "1.126.0", @@ -162,11 +162,11 @@ "uuid": "3.3.3", "validate.js": "0.13.1", "winston": "3.2.1", - "yargs": "14.0.0" + "yargs": "14.2.0" }, "devDependencies": { - "@babel/cli": "^7.6.2", - "@babel/core": "^7.6.2", + "@babel/cli": "^7.6.4", + "@babel/core": "^7.6.4", "@babel/plugin-proposal-class-properties": "^7.5.0", "@babel/plugin-proposal-decorators": "^7.6.0", "@babel/plugin-proposal-export-namespace-from": "^7.5.2", @@ -177,11 +177,11 @@ "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-import-meta": "^7.2.0", "@babel/polyfill": "^7.6.0", - "@babel/preset-env": "^7.6.2", - "@mdi/font": "4.4.95", + "@babel/preset-env": "^7.6.3", + "@mdi/font": "4.5.95", "@panter/vue-i18next": "0.15.1", "@requarks/ckeditor5": "12.4.0-wiki.14", - "@vue/babel-preset-app": "3.11.0", + "@vue/babel-preset-app": "3.12.0", "animate-sass": "0.8.2", "animated-number-vue": "1.0.0", "apollo-cache-inmemory": "1.6.3", @@ -193,7 +193,7 @@ "apollo-link-persisted-queries": "0.2.2", "apollo-link-ws": "1.0.19", "apollo-utilities": "1.3.2", - "autoprefixer": "9.6.1", + "autoprefixer": "9.6.4", "babel-eslint": "10.0.3", "babel-jest": "24.9.0", "babel-loader": "^8.0.6", @@ -211,7 +211,7 @@ "cssnano": "4.1.10", "duplicate-package-checker-webpack-plugin": "3.0.0", "epic-spinners": "1.1.0", - "eslint": "6.4.0", + "eslint": "6.5.1", "eslint-config-requarks": "1.0.7", "eslint-config-standard": "14.1.0", "eslint-plugin-import": "2.18.2", @@ -223,7 +223,7 @@ "file-loader": "4.2.0", "filepond": "4.7.2", "filepond-plugin-file-validate-type": "1.2.4", - "filesize.js": "1.0.2", + "filesize.js": "2.0.0", "graphiql": "0.14.2", "graphql-persisted-document-loader": "1.0.1", "graphql-tag": "^2.10.1", @@ -253,19 +253,19 @@ "pug-plain-loader": "1.0.0", "raw-loader": "3.1.0", "resolve-url-loader": "3.1.0", - "sass": "1.22.12", + "sass": "1.23.0", "sass-loader": "8.0.0", "sass-resources-loader": "2.0.1", "script-ext-html-webpack-plugin": "2.1.4", "simple-progress-webpack-plugin": "1.1.2", "style-loader": "1.0.0", - "terser": "4.3.3", + "terser": "4.3.8", "twemoji-awesome": "1.0.6", - "url-loader": "2.1.0", + "url-loader": "2.2.0", "velocity-animate": "1.5.2", "viz.js": "2.1.2", "vue": "2.6.10", - "vue-apollo": "3.0.0-rc.6", + "vue-apollo": "3.0.0-rc.7", "vue-chartjs": "3.4.2", "vue-clipboards": "1.3.0", "vue-filepond": "5.1.3", @@ -278,22 +278,22 @@ "vue2-animate": "2.1.2", "vuedraggable": "2.23.2", "vuescroll": "4.14.4", - "vuetify": "2.0.19", + "vuetify": "2.1.3", "vuetify-loader": "1.3.0", "vuex": "3.1.1", "vuex-pathify": "1.4.0", "vuex-persistedstate": "2.5.4", - "webpack": "4.41.0", + "webpack": "4.41.1", "webpack-bundle-analyzer": "3.5.2", "webpack-cli": "3.3.9", - "webpack-dev-middleware": "3.7.1", + "webpack-dev-middleware": "3.7.2", "webpack-hot-middleware": "2.25.0", "webpack-merge": "4.2.2", - "webpack-subresource-integrity": "1.3.3", + "webpack-subresource-integrity": "1.3.4", "webpackbar": "4.0.0", "whatwg-fetch": "3.0.0", "write-file-webpack-plugin": "4.5.1", - "xterm": "4.0.2", + "xterm": "4.1.0", "zxcvbn": "4.4.2" }, "browserslist": [ diff --git a/server/app/data.yml b/server/app/data.yml index 5c289da9..77583fd2 100644 --- a/server/app/data.yml +++ b/server/app/data.yml @@ -46,6 +46,7 @@ defaults: securityIframe: true securityReferrerPolicy: true securityTrustProxy: true + securitySRI: true securityHSTS: false securityHSTSDuration: 300 securityCSP: false diff --git a/server/graph/resolvers/site.js b/server/graph/resolvers/site.js index f4cad189..8629df72 100644 --- a/server/graph/resolvers/site.js +++ b/server/graph/resolvers/site.js @@ -47,6 +47,7 @@ module.exports = { securityIframe: args.securityIframe, securityReferrerPolicy: args.securityReferrerPolicy, securityTrustProxy: args.securityTrustProxy, + securitySRI: args.securitySRI, securityHSTS: args.securityHSTS, securityHSTSDuration: args.securityHSTSDuration, securityCSP: args.securityCSP, diff --git a/server/graph/schemas/site.graphql b/server/graph/schemas/site.graphql index 0ce83ac5..b3517795 100644 --- a/server/graph/schemas/site.graphql +++ b/server/graph/schemas/site.graphql @@ -39,6 +39,7 @@ type SiteMutation { securityIframe: Boolean! securityReferrerPolicy: Boolean! securityTrustProxy: Boolean! + securitySRI: Boolean! securityHSTS: Boolean! securityHSTSDuration: Int! securityCSP: Boolean! @@ -66,6 +67,7 @@ type SiteConfig { securityIframe: Boolean! securityReferrerPolicy: Boolean! securityTrustProxy: Boolean! + securitySRI: Boolean! securityHSTS: Boolean! securityHSTSDuration: Int! securityCSP: Boolean! diff --git a/yarn.lock b/yarn.lock index fd8a3cb1..e7e6b3d9 100644 Binary files a/yarn.lock and b/yarn.lock differ