Browse Source

feat: SRI security toggle

NGPixel 5 years ago
parent
commit
acb57879dd

+ 12 - 0
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),

+ 20 - 3
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
     }
   }

+ 1 - 0
client/graph/admin/site/site-query-config.gql

@@ -16,6 +16,7 @@
       securityIframe
       securityReferrerPolicy
       securityTrustProxy
+      securitySRI
       securityHSTS
       securityHSTSDuration
       securityCSP

+ 0 - 19
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

+ 3 - 3
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 { %>

+ 35 - 35
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": [

+ 1 - 0
server/app/data.yml

@@ -46,6 +46,7 @@ defaults:
       securityIframe: true
       securityReferrerPolicy: true
       securityTrustProxy: true
+      securitySRI: true
       securityHSTS: false
       securityHSTSDuration: 300
       securityCSP: false

+ 1 - 0
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,

+ 2 - 0
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!

File diff suppressed because it is too large
+ 325 - 223
yarn.lock


Some files were not shown because too many files changed in this diff