Преглед изворни кода

Merge commit 'd5b5ce30d0d38900b80cbef02bb25c8a3a775fd2' into imprv/improve-link-edit-modal

yusuketk пре 5 година
родитељ
комит
6e110fb8dd

+ 9 - 6
src/client/js/components/Page/RevisionLoader.jsx

@@ -22,7 +22,7 @@ class RevisionLoader extends React.Component {
       markdown: '',
       isLoading: false,
       isLoaded: false,
-      error: null,
+      errors: null,
     };
 
     this.loadData = this.loadData.bind(this);
@@ -49,15 +49,15 @@ class RevisionLoader extends React.Component {
 
       this.setState({
         markdown: res.data.revision.body,
-        error: null,
+        errors: null,
       });
 
       if (this.props.onRevisionLoaded != null) {
         this.props.onRevisionLoaded(res.data.revision);
       }
     }
-    catch (error) {
-      this.setState({ error });
+    catch (errors) {
+      this.setState({ errors });
     }
     finally {
       this.setState({ isLoaded: true, isLoading: false });
@@ -94,8 +94,11 @@ class RevisionLoader extends React.Component {
 
     // ----- after load -----
     let markdown = this.state.markdown;
-    if (this.state.error != null) {
-      markdown = `<span class="text-muted"><em>${this.state.error}</em></span>`;
+    if (this.state.errors != null) {
+      const errorMessages = this.state.errors.map((error) => {
+        return `<span class="text-muted"><em>${error.message}</em></span>`;
+      });
+      markdown = errorMessages.join('');
     }
 
     return (

+ 4 - 6
src/client/styles/scss/theme/_apply-colors-dark.scss

@@ -47,12 +47,6 @@ textarea.form-control {
   // border: 1px solid darken($border, 30%);
 }
 
-.grw-slack-notification {
-  .form-control {
-    background: $bgcolor-global;
-  }
-}
-
 .form-control[disabled],
 .form-control[readonly] {
   color: lighten($color-global, 10%);
@@ -317,6 +311,10 @@ ul.pagination {
   background-color: transparent;
   $color-slack: #4b144c;
 
+  .form-control {
+    background: $bgcolor-global;
+  }
+
   .custom-control-label {
     &::before {
       background-color: $secondary;

+ 6 - 6
src/client/styles/scss/theme/_apply-colors-light.scss

@@ -38,12 +38,6 @@ $border-color: $border-color-global;
   background-color: $bgcolor-global;
 }
 
-.grw-slack-notification {
-  .form-control {
-    background: white;
-  }
-}
-
 .form-control::placeholder {
   color: darken($bgcolor-global, 20%);
 }
@@ -191,6 +185,8 @@ $border-color: $border-color-global;
  * GROWI on-edit
  */
 .grw-editor-navbar-bottom {
+  background-color: $gray-50;
+
   #slack-mark-white {
     display: none;
   }
@@ -222,6 +218,10 @@ $border-color: $border-color-global;
   background-color: white;
   $color-slack: #4b144c;
 
+  .form-control {
+    background: white;
+  }
+
   .custom-control-label {
     &::before {
       background-color: $gray-200;

+ 0 - 4
src/client/styles/scss/theme/_apply-colors.scss

@@ -433,10 +433,6 @@ body.on-edit {
       border-top-color: $border-color-theme;
     }
   }
-
-  .grw-editor-navbar-bottom {
-    background-color: $gray-50;
-  }
 }
 
 /*

+ 1 - 1
src/server/routes/admin.js

@@ -325,7 +325,7 @@ module.exports = function(crowi, app) {
 
   api.validators.export.download = function() {
     const validator = [
-      // https://regex101.com/r/mD4eZs/4
+      // https://regex101.com/r/mD4eZs/6
       // prevent from pass traversal attack
       param('fileName').not().matches(/(\.\.\/|\.\.\\)/),
     ];

+ 1 - 1
src/server/routes/apiv3/export.js

@@ -62,7 +62,7 @@ module.exports = (crowi) => {
 
   const validator = {
     deleteFile: [
-      // https://regex101.com/r/mD4eZs/4
+      // https://regex101.com/r/mD4eZs/6
       // prevent from unexpecting attack doing delete file (path traversal attack)
       param('fileName').not().matches(/(\.\.\/|\.\.\\)/),
     ],

+ 1 - 1
src/server/routes/attachment.js

@@ -239,7 +239,7 @@ module.exports = function(crowi, app) {
     else {
       res.set({
         'Content-Type': attachment.fileFormat,
-        'Content-Security-Policy': "script-src 'unsafe-hashes'",
+        'Content-Security-Policy': "script-src 'unsafe-hashes'; object-src 'none'; require-trusted-types-for 'script'; default-src 'none';",
       });
     }
   }

+ 6 - 1
src/server/routes/tag.js

@@ -82,7 +82,12 @@ module.exports = function(crowi, app) {
    * @apiParam {String} q keyword
    */
   api.search = async function(req, res) {
-    let tags = await Tag.find({ name: new RegExp(`^${req.query.q}`) }).select('-_id name');
+    // https://regex101.com/r/J1cN6O/1
+    // prevent from unexpecting attack doing regular expression on tag search (DoS attack)
+    // Search for regular expressions as normal characters
+    // e.g. user*$ -> user\*\$ (escape a regular expression)
+    const escapeRegExp = req.query.q.replace(/[\\^$/.*+?()[\]{}|]/g, '\\$&');
+    let tags = await Tag.find({ name: new RegExp(`^${escapeRegExp}`) }).select('_id name');
     tags = tags.map((tag) => { return tag.name });
     return res.json(ApiResponse.success({ tags }));
   };

+ 1 - 1
src/server/service/import.js

@@ -369,7 +369,7 @@ class ImportService {
 
     unzipStream.on('entry', (entry) => {
       const fileName = entry.path;
-      // https://regex101.com/r/mD4eZs/4
+      // https://regex101.com/r/mD4eZs/6
       // prevent from unexpecting attack doing unzip file (path traversal attack)
       // FOR EXAMPLE
       // ../../src/server/views/admin/markdown.html