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

Merge pull request #1243 from weseek/create-xss-post-apiV3

Create xss post api v3
Yuki Takei пре 6 година
родитељ
комит
da9e140eb5

+ 2 - 2
src/client/js/components/Admin/MarkdownSetting/LineBreakSetting.jsx

@@ -42,8 +42,8 @@ class LineBreakSetting extends React.Component {
       isEnabledLinebreaksInComments: this.state.isEnabledLinebreaksInComments,
       isEnabledLinebreaksInComments: this.state.isEnabledLinebreaksInComments,
     };
     };
     try {
     try {
-      await appContainer.apiPost('/admin/markdown/lineBreaksSetting', { params });
-      toastSuccess('Success change line braek setting');
+      await appContainer.apiPost('/admin/markdown/lineBreaksSetting', params);
+      toastSuccess('Success update line braek setting');
     }
     }
     catch (err) {
     catch (err) {
       toastError(err);
       toastError(err);

+ 15 - 5
src/client/js/components/Admin/MarkdownSetting/WhiteListInput.jsx

@@ -10,16 +10,26 @@ import MarkDownSettingContainer from '../../../services/MarkDownSettingContainer
 
 
 class WhiteListInput extends React.Component {
 class WhiteListInput extends React.Component {
 
 
-  renderRecommendBtn() {
-    const { t } = this.props;
+  renderRecommendTagBtn() {
+    const { t, markDownSettingContainer } = this.props;
 
 
     return (
     return (
-      <p id="btn-import-tags" className="btn btn-xs btn-primary">
+      <p id="btn-import-tags" className="btn btn-xs btn-primary" onClick={() => { markDownSettingContainer.setState({ tagWhiteList: tags }) }}>
         { t('markdown_setting.import_recommended', 'tags') }
         { t('markdown_setting.import_recommended', 'tags') }
       </p>
       </p>
     );
     );
   }
   }
 
 
+  renderRecommendAttrBtn() {
+    const { t, markDownSettingContainer } = this.props;
+
+    return (
+      <p id="btn-import-tags" className="btn btn-xs btn-primary" onClick={() => { markDownSettingContainer.setState({ attrWhiteList: attrs }) }}>
+        { t('markdown_setting.import_recommended', 'Attrs') }
+      </p>
+    );
+  }
+
   renderTagValue() {
   renderTagValue() {
     const { customizable, markDownSettingContainer } = this.props;
     const { customizable, markDownSettingContainer } = this.props;
 
 
@@ -48,7 +58,7 @@ class WhiteListInput extends React.Component {
         <div className="m-t-15">
         <div className="m-t-15">
           <div className="d-flex justify-content-between">
           <div className="d-flex justify-content-between">
             { t('markdown_setting.Tag names') }
             { t('markdown_setting.Tag names') }
-            {customizable && this.renderRecommendBtn()}
+            {customizable && this.renderRecommendTagBtn()}
           </div>
           </div>
           <textarea
           <textarea
             className="form-control xss-list"
             className="form-control xss-list"
@@ -63,7 +73,7 @@ class WhiteListInput extends React.Component {
         <div className="m-t-15">
         <div className="m-t-15">
           <div className="d-flex justify-content-between">
           <div className="d-flex justify-content-between">
             { t('markdown_setting.Tag attributes') }
             { t('markdown_setting.Tag attributes') }
-            {customizable && this.renderRecommendBtn()}
+            {customizable && this.renderRecommendAttrBtn()}
           </div>
           </div>
           <textarea
           <textarea
             className="form-control xss-list"
             className="form-control xss-list"

+ 12 - 1
src/client/js/components/Admin/MarkdownSetting/XssForm.jsx

@@ -1,14 +1,18 @@
 import React from 'react';
 import React from 'react';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import { withTranslation } from 'react-i18next';
+import loggerFactory from '@alias/logger';
 
 
 import { createSubscribedElement } from '../../UnstatedUtils';
 import { createSubscribedElement } from '../../UnstatedUtils';
+import { toastSuccess, toastError } from '../../../util/apiNotification';
 
 
 import AppContainer from '../../../services/AppContainer';
 import AppContainer from '../../../services/AppContainer';
 import MarkDownSettingContainer from '../../../services/MarkDownSettingContainer';
 import MarkDownSettingContainer from '../../../services/MarkDownSettingContainer';
 
 
 import WhiteListInput from './WhiteListInput';
 import WhiteListInput from './WhiteListInput';
 
 
+const logger = loggerFactory('growi:importer');
+
 class XssForm extends React.Component {
 class XssForm extends React.Component {
 
 
   constructor(props) {
   constructor(props) {
@@ -18,7 +22,14 @@ class XssForm extends React.Component {
   }
   }
 
 
   async onClickSubmit() {
   async onClickSubmit() {
-    // TODO GW-303 create apiV3 of update setting
+    try {
+      await this.props.markDownSettingContainer.updateXssSetting();
+      toastSuccess('Success update Xss setting');
+    }
+    catch (err) {
+      toastError(err);
+      logger.error(err);
+    }
   }
   }
 
 
   xssOptions() {
   xssOptions() {

+ 15 - 0
src/client/js/services/MarkDownSettingContainer.js

@@ -38,4 +38,19 @@ export default class MarkDownSettingContainer extends Container {
     this.setState({ isEnabledXss: !this.state.isEnabledXss });
     this.setState({ isEnabledXss: !this.state.isEnabledXss });
   }
   }
 
 
+  /**
+   * Update Xss Setting
+   */
+  async updateXssSetting() {
+
+    const response = await this.appContainer.apiv3.put('/markdown-setting/xss', {
+      isEnabledXss: this.state.isEnabledXss,
+      xssOption: this.state.xssOption,
+      tagWhiteList: this.state.tagWhiteList,
+      attrWhiteList: this.state.attrWhiteList,
+    });
+
+    return response;
+  }
+
 }
 }

+ 4 - 24
src/server/routes/admin.js

@@ -132,7 +132,10 @@ module.exports = function(crowi, app) {
   // app.post('/admin/markdown/lineBreaksSetting' , admin.markdown.lineBreaksSetting);
   // app.post('/admin/markdown/lineBreaksSetting' , admin.markdown.lineBreaksSetting);
   actions.markdown.lineBreaksSetting = async function(req, res) {
   actions.markdown.lineBreaksSetting = async function(req, res) {
 
 
-    const array = req.body.params;
+    const array = {
+      'markdown:isEnabledLinebreaks': req.body.isEnabledLinebreaks,
+      'markdown:isEnabledLinebreaksInComments': req.body.isEnabledLinebreaksInComments,
+    };
 
 
     try {
     try {
       await configManager.updateConfigsInTheSameNamespace('markdown', array);
       await configManager.updateConfigsInTheSameNamespace('markdown', array);
@@ -159,29 +162,6 @@ module.exports = function(crowi, app) {
     return res.redirect('/admin/markdown');
     return res.redirect('/admin/markdown');
   };
   };
 
 
-  // app.post('/admin/markdown/xss-setting' , admin.markdown.xssSetting);
-  actions.markdown.xssSetting = async function(req, res) {
-    const xssSetting = req.form.markdownSetting;
-
-    xssSetting['markdown:xss:tagWhiteList'] = csvToArray(xssSetting['markdown:xss:tagWhiteList']);
-    xssSetting['markdown:xss:attrWhiteList'] = csvToArray(xssSetting['markdown:xss:attrWhiteList']);
-
-    if (req.form.isValid) {
-      await configManager.updateConfigsInTheSameNamespace('markdown', xssSetting);
-      req.flash('successMessage', ['Successfully updated!']);
-    }
-    else {
-      req.flash('errorMessage', req.form.errors);
-    }
-
-    return res.redirect('/admin/markdown');
-  };
-
-  const csvToArray = (string) => {
-    const array = string.split(',');
-    return array.map((item) => { return item.trim() });
-  };
-
   // app.get('/admin/customize' , admin.customize.index);
   // app.get('/admin/customize' , admin.customize.index);
   actions.customize = {};
   actions.customize = {};
   actions.customize.index = function(req, res) {
   actions.customize.index = function(req, res) {

+ 83 - 0
src/server/routes/apiv3/markdown-setting.js

@@ -7,6 +7,10 @@ const express = require('express');
 
 
 const router = express.Router();
 const router = express.Router();
 
 
+const { body } = require('express-validator/check');
+
+const validator = {};
+
 /**
 /**
  * @swagger
  * @swagger
  *  tags:
  *  tags:
@@ -16,11 +20,90 @@ const router = express.Router();
 module.exports = (crowi) => {
 module.exports = (crowi) => {
   const loginRequiredStrictly = require('../../middleware/login-required')(crowi);
   const loginRequiredStrictly = require('../../middleware/login-required')(crowi);
   const adminRequired = require('../../middleware/admin-required')(crowi);
   const adminRequired = require('../../middleware/admin-required')(crowi);
+  const csrf = require('../../middleware/csrf')(crowi);
 
 
   const {
   const {
     ErrorV3,
     ErrorV3,
     Config,
     Config,
   } = crowi.models;
   } = crowi.models;
 
 
+  const { ApiV3FormValidator } = crowi.middlewares;
+
+  validator.xssSetting = [
+    body('isEnabledXss').isBoolean(),
+    body('tagWhiteList').isArray(),
+    body('attrWhiteList').isArray(),
+  ];
+
+  /**
+   * @swagger
+   *
+   *  paths:
+   *    /_api/v3/markdown-setting/xss:
+   *      put:
+   *        tags: [Users]
+   *        description: Update xss
+   *        parameters:
+   *          - name: markdown:xss:isEnabledPrevention
+   *            in: query
+   *            description: enable xss
+   *            schema:
+   *              type: boolean
+   *          - name: markdown:xss:option
+   *            in: query
+   *            description: xss option
+   *            schema:
+   *              type: number
+   *          - name: markdown:xss:tagWhiteList
+   *            in: query
+   *            description: custom tag whitelist
+   *            schema:
+   *              type: array
+   *              items:
+   *                type: string
+   *                description: tag whitelist
+   *          - name: markdown:xss:attrWhiteList
+   *            in: query
+   *            description: custom attr whitelist
+   *            schema:
+   *              type: array
+   *              items:
+   *                type: string
+   *                description: tag whitelist
+   *        responses:
+   *          200:
+   *            description: Updating xss success
+   *            content:
+   *              application/json:
+   *                schema:
+   *                  properties:
+   *                    xssParams:
+   *                      type: object
+   *                      description: new xss params
+   */
+  router.put('/xss', loginRequiredStrictly, adminRequired, csrf, validator.xssSetting, ApiV3FormValidator, async(req, res) => {
+    if (req.body.isEnabledXss && req.body.xssOption == null) {
+      return res.apiv3Err(new ErrorV3('xss option is required'));
+    }
+
+    const xssParams = {
+      'markdown:xss:isEnabledPrevention': req.body.isEnabledXss,
+      'markdown:xss:option': req.body.xssOption,
+      'markdown:xss:tagWhiteList': req.body.tagWhiteList,
+      'markdown:xss:attrWhiteList': req.body.attrWhiteList,
+    };
+
+    try {
+      await crowi.configManager.updateConfigsInTheSameNamespace('markdown', xssParams);
+      return res.apiv3({ xssParams });
+    }
+    catch (err) {
+      const msg = 'Error occurred in updating xss';
+      logger.error('Error', err);
+      return res.apiv3Err(new ErrorV3(msg, 'update-xss-failed'));
+    }
+
+  });
+
   return router;
   return router;
 };
 };

+ 0 - 1
src/server/routes/index.js

@@ -93,7 +93,6 @@ module.exports = function(crowi, app) {
   // markdown admin
   // markdown admin
   app.get('/admin/markdown'                   , loginRequiredStrictly , adminRequired , admin.markdown.index); // TODO delete
   app.get('/admin/markdown'                   , loginRequiredStrictly , adminRequired , admin.markdown.index); // TODO delete
   app.post('/_api/admin/markdown/lineBreaksSetting', loginRequiredStrictly , adminRequired , csrf, form.admin.markdown, admin.markdown.lineBreaksSetting); // change form name
   app.post('/_api/admin/markdown/lineBreaksSetting', loginRequiredStrictly , adminRequired , csrf, form.admin.markdown, admin.markdown.lineBreaksSetting); // change form name
-  app.post('/admin/markdown/xss-setting'      , loginRequiredStrictly , adminRequired , csrf, form.admin.markdownXss, admin.markdown.xssSetting);
   app.post('/admin/markdown/presentationSetting', loginRequiredStrictly , adminRequired , csrf, form.admin.markdownPresentation, admin.markdown.presentationSetting);
   app.post('/admin/markdown/presentationSetting', loginRequiredStrictly , adminRequired , csrf, form.admin.markdownPresentation, admin.markdown.presentationSetting);
 
 
   // markdown admin
   // markdown admin