Просмотр исходного кода

Merge pull request #1222 from weseek/create-XSS-form

Create xss form
Yuki Takei 6 лет назад
Родитель
Сommit
0912ea5182

+ 3 - 20
src/client/js/components/Admin/MarkdownSetting/MarkDownSetting.jsx

@@ -6,6 +6,7 @@ import { withTranslation } from 'react-i18next';
 import { createSubscribedElement } from '../../UnstatedUtils';
 
 import AppContainer from '../../../services/AppContainer';
+import XssForm from './XssForm';
 
 class MarkdownSetting extends React.Component {
 
@@ -21,8 +22,6 @@ class MarkdownSetting extends React.Component {
       pageBreakOption: 1,
       // TODO GW-258 get correct custom regular expression
       customRegularExpression: '',
-      // TODO GW-221 get correct Xss value
-      isEnabledXss: false,
     };
 
     this.handleInputChange = this.handleInputChange.bind(this);
@@ -130,29 +129,13 @@ class MarkdownSetting extends React.Component {
 
           </fieldset>
         </div>
-
+        {/* XSS Setting */}
         <div className="row my-3">
           <div className="form-group">
             <legend>{ t('markdown_setting.XSS_setting') }</legend>
             <p className="well">{ t('markdown_setting.XSS_setting_desc') }</p>
           </div>
-          <fieldset className="row">
-            <div className="form-group">
-              <label className="col-xs-4 control-label text-right">
-                { t('markdown_setting.Enable XSS prevention') }
-              </label>
-              <div className="col-xs-5">
-                <input type="checkbox" name="isEnabledXss" checked={this.state.isEnabledXss} onChange={this.handleInputChange} />
-              </div>
-            </div>
-
-            <div className="form-group my-3">
-              <div className="col-xs-offset-4 col-xs-5">
-                <button type="submit" className="btn btn-primary">{ t('Update') }</button>
-              </div>
-            </div>
-
-          </fieldset>
+          <XssForm />
         </div>
       </React.Fragment>
     );

+ 63 - 0
src/client/js/components/Admin/MarkdownSetting/WhiteListInput.jsx

@@ -0,0 +1,63 @@
+/* eslint-disable max-len */
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+
+import { createSubscribedElement } from '../../UnstatedUtils';
+
+import AppContainer from '../../../services/AppContainer';
+
+class WhiteListInput extends React.Component {
+
+  renderRecommendBtn() {
+    const { t } = this.props;
+
+    return (
+      <p id="btn-import-tags" className="btn btn-xs btn-primary">
+        { t('markdown_setting.import_recommended', 'tags') }
+      </p>
+    );
+  }
+
+  render() {
+    const { t, customizable } = this.props;
+    const { onChangeTagWhiteList, onChangeAttrWhiteList } = this.props;
+
+    return (
+      <>
+        <div className="m-t-15">
+          <div className="d-flex justify-content-between">
+            { t('markdown_setting.Tag names') }
+            {customizable && this.renderRecommendBtn()}
+          </div>
+          {/* TODO GW-304 fetch correct defaultValue */}
+          <textarea className="form-control xss-list" name="recommendedTags" rows="6" cols="40" readOnly={!customizable} defaultValue="recommendedWhitelist.tags" onChange={(e) => { onChangeTagWhiteList(e.target.value) }} />
+        </div>
+        <div className="m-t-15">
+          <div className="d-flex justify-content-between">
+            { t('markdown_setting.Tag attributes') }
+            {customizable && this.renderRecommendBtn()}
+          </div>
+          {/* TODO GW-304 fetch correct defaultValue */}
+          <textarea className="form-control xss-list" name="recommendedAttrs" rows="6" cols="40" readOnly={!customizable} defaultValue="recommendedWhitelist.attrs" onChange={(e) => { onChangeAttrWhiteList(e.target.value) }} />
+        </div>
+      </>
+    );
+  }
+
+}
+
+const WhiteListWrapper = (props) => {
+  return createSubscribedElement(WhiteListInput, props, [AppContainer]);
+};
+
+WhiteListInput.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+
+  customizable: PropTypes.bool.isRequired,
+  onChangeTagWhiteList: PropTypes.func,
+  onChangeAttrWhiteList: PropTypes.func,
+};
+
+export default withTranslation()(WhiteListWrapper);

+ 135 - 0
src/client/js/components/Admin/MarkdownSetting/XssForm.jsx

@@ -0,0 +1,135 @@
+/* eslint-disable react/no-unused-state */
+/* eslint-disable max-len */
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+
+import { createSubscribedElement } from '../../UnstatedUtils';
+
+import AppContainer from '../../../services/AppContainer';
+import WhiteListInput from './WhiteListInput';
+
+class XssForm extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    const { appContainer } = this.props;
+
+    this.state = {
+      // TODO GW-304 fetch correct value
+      isEnabledXss: false,
+      XssOption: 1,
+      tagWhiteList: appContainer.config.tagWhiteList,
+      attrWhiteList: '',
+    };
+
+    this.onChangeEnableXss = this.onChangeEnableXss.bind(this);
+    this.onChangeXssOption = this.onChangeXssOption.bind(this);
+    this.onChangeTagWhiteList = this.onChangeTagWhiteList.bind(this);
+    this.onChangeAttrWhiteList = this.onChangeAttrWhiteList.bind(this);
+    this.onClickSubmit = this.onClickSubmit.bind(this);
+  }
+
+  onChangeEnableXss() {
+    this.setState({ isEnabledXss: !this.state.isEnabledXss });
+  }
+
+  onChangeXssOption(value) {
+    this.setState({ XssOption: value });
+  }
+
+  onChangeTagWhiteList(value) {
+    this.setState({ tagWhiteList: value });
+  }
+
+  onChangeAttrWhiteList(value) {
+    this.setState({ attrWhiteList: value });
+  }
+
+  async componentDidMount() {
+    await this.syncXssSettings();
+  }
+
+  async onClickSubmit() {
+    // TODO GW-303 create apiV3 of update setting
+  }
+
+  async syncXssSettings() {
+    // TODO GW-304 createApiV3
+  }
+
+  xssOptions() {
+    const { t } = this.props;
+
+    return (
+      <fieldset className="form-group col-xs-12 my-3">
+        <div className="col-xs-4 radio radio-primary">
+          <input type="radio" id="xssOption1" name="XssOption" onChange={() => { this.onChangeXssOption(1) }} />
+          <label htmlFor="xssOption1">
+            <p className="font-weight-bold">{ t('markdown_setting.Ignore all tags') }</p>
+            <div className="m-t-15">
+              { t('markdown_setting.Ignore all tags desc') }
+            </div>
+          </label>
+        </div>
+
+        <div className="col-xs-4 radio radio-primary">
+          <input type="radio" id="xssOption2" name="XssOption" onChange={() => { this.onChangeXssOption(2) }} />
+          <label htmlFor="xssOption2">
+            <p className="font-weight-bold">{ t('markdown_setting.Recommended setting') }</p>
+            <WhiteListInput customizable={false} />
+          </label>
+        </div>
+
+        <div className="col-xs-4 radio radio-primary">
+          <input type="radio" id="xssOption3" name="XssOption" onChange={() => { this.onChangeXssOption(3) }} />
+          <label htmlFor="xssOption3">
+            <p className="font-weight-bold">{ t('markdown_setting.Custom Whitelist') }</p>
+            <WhiteListInput customizable onChangeTagWhiteList={this.onChangeTagWhiteList} onChangeAttrWhiteList={this.onChangeAttrWhiteList} />
+          </label>
+        </div>
+      </fieldset>
+    );
+  }
+
+  render() {
+    const { t } = this.props;
+
+    return (
+      <React.Fragment>
+        <form className="row">
+          <div className="form-group">
+            <div className="col-xs-4 text-right">
+              <div className="checkbox checkbox-success" onChange={this.onChangeEnableXss}>
+                <input type="checkbox" id="XssEnable" className="form-check-input" name="isEnabledXss" checked={this.state.isEnabledXss} />
+                <label htmlFor="XssEnable">
+                  { t('markdown_setting.Enable XSS prevention') }
+                </label>
+              </div>
+            </div>
+            {this.state.isEnabledXss && this.xssOptions()}
+          </div>
+          <div className="form-group my-3">
+            <div className="col-xs-offset-4 col-xs-5">
+              <div className="btn btn-primary" onClick={this.onClickSubmit}>{ t('Update') }</div>
+            </div>
+          </div>
+        </form>
+      </React.Fragment>
+    );
+  }
+
+}
+
+const XssFormWrapper = (props) => {
+  return createSubscribedElement(XssForm, props, [AppContainer]);
+};
+
+XssForm.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+
+};
+
+export default withTranslation()(XssFormWrapper);