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

Merge pull request #1433 from weseek/reactify-security-reflect-api

Reactify security reflect api
Kaito Mishina 6 лет назад
Родитель
Сommit
22b511a54d

+ 1 - 0
resource/locales/en-US/translation.json

@@ -475,6 +475,7 @@
     "desc_of_callback_URL": "Use it in the setting of the {{AuthName}} Identity provider",
     "desc_of_callback_URL": "Use it in the setting of the {{AuthName}} Identity provider",
     "clientID": "Client ID",
     "clientID": "Client ID",
     "client_secret": "Client Secret",
     "client_secret": "Client Secret",
+    "updated_general_security_setting": "Succeeded to update security setting",
     "guest_mode": {
     "guest_mode": {
       "deny": "Deny (Registered Users Only)",
       "deny": "Deny (Registered Users Only)",
       "readonly": "Accept (Guests can read only)"
       "readonly": "Accept (Guests can read only)"

+ 1 - 0
resource/locales/ja/translation.json

@@ -470,6 +470,7 @@
     "desc_of_callback_URL": "{{AuthName}} プロバイダ側の設定で利用してください。",
     "desc_of_callback_URL": "{{AuthName}} プロバイダ側の設定で利用してください。",
     "clientID": "クライアントID",
     "clientID": "クライアントID",
     "client_secret": "クライアントシークレット",
     "client_secret": "クライアントシークレット",
+    "updated_general_security_setting": "セキュリティ設定を更新しました。",
     "guest_mode": {
     "guest_mode": {
       "deny": "拒否 (アカウントを持つユーザーのみ利用可能)",
       "deny": "拒否 (アカウントを持つユーザーのみ利用可能)",
       "readonly": "許可 (ゲストユーザーも閲覧のみ可能)"
       "readonly": "許可 (ゲストユーザーも閲覧のみ可能)"

+ 1 - 1
src/client/js/app.jsx

@@ -234,7 +234,7 @@ if (adminSecuritySettingElem != null) {
     adminGoogleSecurityContainer, adminGithubSecurityContainer, adminTwitterSecurityContainer,
     adminGoogleSecurityContainer, adminGithubSecurityContainer, adminTwitterSecurityContainer,
   ];
   ];
   ReactDOM.render(
   ReactDOM.render(
-    <Provider inject={[injectableContainers, adminSecurityContainers]}>
+    <Provider inject={[...injectableContainers, ...adminSecurityContainers]}>
       <I18nextProvider i18n={i18n}>
       <I18nextProvider i18n={i18n}>
         <SecurityManagement />
         <SecurityManagement />
       </I18nextProvider>
       </I18nextProvider>

+ 2 - 76
src/client/js/components/Admin/Security/SecurityManagement.jsx

@@ -9,6 +9,7 @@ import LdapSecuritySetting from './LdapSecuritySetting';
 import LocalSecuritySetting from './LocalSecuritySetting';
 import LocalSecuritySetting from './LocalSecuritySetting';
 import SamlSecuritySetting from './SamlSecuritySetting';
 import SamlSecuritySetting from './SamlSecuritySetting';
 import OidcSecuritySetting from './OidcSecuritySetting';
 import OidcSecuritySetting from './OidcSecuritySetting';
+import SecuritySetting from './SecuritySetting';
 import BasicSecuritySetting from './BasicSecuritySetting';
 import BasicSecuritySetting from './BasicSecuritySetting';
 import GoogleSecuritySetting from './GoogleSecuritySetting';
 import GoogleSecuritySetting from './GoogleSecuritySetting';
 import GithubSecuritySetting from './GithubSecuritySetting';
 import GithubSecuritySetting from './GithubSecuritySetting';
@@ -26,82 +27,7 @@ class SecurityManagement extends React.Component {
     const { t } = this.props;
     const { t } = this.props;
     return (
     return (
       <Fragment>
       <Fragment>
-        {/* TODO GW-582 reactify-admin */}
-        <fieldset>
-          <legend className="alert-anchor">{ t('security_settings') }</legend>
-          <div className="form-group">
-            <label htmlFor="settingForm[security:restrictGuestMode]" className="col-xs-3 control-label">{ t('security_setting.Guest Users Access') }</label>
-            <div className="col-xs-6">
-              <select
-                className="form-control selectpicker"
-                name="settingForm[security:restrictGuestMode]"
-                value="{ getConfig('crowi', 'security:restrictGuestMode') }"
-              >
-                <option value="{ t(modeValue) }">{ t('modeLabel') }</option>
-              </select>
-              <p className="alert alert-warning mt-2">
-                <i className="icon-exclamation icon-fw">
-                </i><b>FIXED</b>
-                { t('security_setting.Fixed by env var', 'FORCE_WIKI_MODE') }<br></br>
-              </p>
-            </div>
-          </div>
-          <div className="form-group">
-            <label htmlFor="{{configName}}" className="col-xs-3 control-label">{ t('security_setting.page_listing_1') }</label>
-            <div className="col-xs-9">
-              <div className="btn-group btn-toggle" data-toggle="buttons">
-                <label className="btn btn-default btn-rounded btn-outline {% if isEnabled %}active{% endif %}" data-active-class="primary">
-                  <input name="{{configName}}" value="false" type="radio"></input>
-                </label>
-                <label className="btn btn-default btn-rounded btn-outline {% if !isEnabled %}active{% endif %}" data-active-class="default">
-                  <input name="{{configName}}" value="true" type="radio"></input>
-                </label>
-              </div>
-              <p className="help-block small">
-                { t('security_setting.page_listing_1_desc') }
-              </p>
-            </div>
-          </div>
-
-          <div className="form-group">
-            <label htmlFor="{{configName}}" className="col-xs-3 control-label">{ t('security_setting.page_listing_2') }</label>
-            <div className="col-xs-9">
-              <div className="btn-group btn-toggle" data-toggle="buttons">
-                <label className="btn btn-default btn-rounded btn-outline {% if isEnabled %}active{% endif %}" data-active-class="primary">
-                  <input name="{{configName}}" value="false" type="radio" />
-                </label>
-                <label className="btn btn-default btn-rounded btn-outline {% if !isEnabled %}active{% endif %}" data-active-class="default">
-                  <input name="{{configName}}" value="true" type="radio" />
-                </label>
-              </div>
-
-              <p className="help-block small">
-                { t('security_setting.page_listing_2_desc') }
-              </p>
-            </div>
-          </div>
-
-          <div className="form-group">
-            <label htmlFor="{{configName}}" className="col-xs-3 control-label">{ t('security_setting.complete_deletion') }</label>
-            <div className="col-xs-6">
-              <select className="form-control selectpicker" name="settingForm[security:pageCompleteDeletionAuthority]" value="{{ configValue }}">
-                <option value="anyOne">{ t('security_setting.anyone') }</option>
-                <option value="adminOnly">{ t('security_setting.admin_only') }</option>
-                <option value="adminAndAuthor">{ t('security_setting.admin_and_author') }</option>
-              </select>
-
-              <p className="help-block small">
-                { t('security_setting.complete_deletion_explain') }
-              </p>
-            </div>
-          </div>
-          {/* TODO GW-540 */}
-          <div className="form-group">
-            <div className="col-xs-offset-3 col-xs-6">
-              <input type="hidden" name="_csrf" value={this.props.csrf} />
-            </div>
-          </div>
-        </fieldset>
+        <div><SecuritySetting /></div>
 
 
         {/* XSS configuration link */}
         {/* XSS configuration link */}
         <div className="mb-5">
         <div className="mb-5">

+ 196 - 0
src/client/js/components/Admin/Security/SecuritySetting.jsx

@@ -0,0 +1,196 @@
+/* eslint-disable react/no-danger */
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withTranslation } from 'react-i18next';
+
+import { createSubscribedElement } from '../../UnstatedUtils';
+import { toastSuccess, toastError } from '../../../util/apiNotification';
+
+import AppContainer from '../../../services/AppContainer';
+import AdminGeneralSecurityContainer from '../../../services/AdminGeneralSecurityContainer';
+
+class SecuritySetting extends React.Component {
+
+  constructor(props) {
+    super(props);
+
+    this.putSecuritySetting = this.putSecuritySetting.bind(this);
+  }
+
+  async putSecuritySetting() {
+    const { t } = this.props;
+    try {
+      await this.props.adminGeneralSecurityContainer.updateGeneralSecuritySetting();
+      toastSuccess(t('security_setting.updated_general_security_setting'));
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }
+
+  render() {
+    const { t, adminGeneralSecurityContainer } = this.props;
+    const helpPageListingByOwner = { __html: t('security_setting.page_listing_1') };
+    const helpPageListingByGroup = { __html: t('security_setting.page_listing_2') };
+    return (
+      <React.Fragment>
+        <fieldset>
+          <legend className="alert-anchor">{ t('security_settings') }</legend>
+          {/* TODO adjust layout */}
+          <div className="row mb-5">
+            <strong className="col-xs-3 text-right"> { t('security_setting.Guest Users Access') } </strong>
+            <div className="col-xs-9 text-left">
+              <div className="my-0 btn-group">
+                <div className="dropdown">
+                  <button
+                    className="btn btn-default dropdown-toggle w-100"
+                    type="button"
+                    data-toggle="dropdown"
+                    aria-haspopup="true"
+                    aria-expanded="false"
+                    disabled={adminGeneralSecurityContainer.state.isWikiModeForced}
+                  >
+                    <span className="pull-left">{t(`security_setting.guest_mode.${adminGeneralSecurityContainer.state.currentRestrictGuestMode}`)}</span>
+                    <span className="bs-caret pull-right">
+                      <span className="caret" />
+                    </span>
+                  </button>
+                  {/* TODO adjust dropdown after BS4 */}
+                  <ul className="dropdown-menu" role="menu">
+                    <li
+                      key="deny"
+                      role="presentation"
+                      type="button"
+                      onClick={() => { adminGeneralSecurityContainer.changeRestrictGuestMode('deny') }}
+                    >
+                      <a role="menuitem">{ t('security_setting.guest_mode.deny') }</a>
+                    </li>
+                    <li
+                      key="readonly"
+                      role="presentation"
+                      type="button"
+                      onClick={() => { adminGeneralSecurityContainer.changeRestrictGuestMode('readonly') }}
+                    >
+                      <a role="menuitem">{ t('security_setting.guest_mode.readonly') }</a>
+                    </li>
+                  </ul>
+                </div>
+              </div>
+            </div>
+          </div>
+          {adminGeneralSecurityContainer.state.isWikiModeForced && (
+            <div className="row mb-5">
+              <div className="col-xs-6">
+                <p className="alert alert-warning mt-2">
+                  <i className="icon-exclamation icon-fw">
+                  </i><b>FIXED</b>
+                  { t('security_setting.Fixed by env var', 'FORCE_WIKI_MODE') }<br></br>
+                </p>
+              </div>
+            </div>
+          )}
+          <div className="row mb-5">
+            <strong className="col-xs-3 text-right" dangerouslySetInnerHTML={helpPageListingByOwner} />
+            <div className="col-xs-6 text-left">
+              <div className="checkbox checkbox-success">
+                <input
+                  id="isHideRestrictedByOwner"
+                  type="checkbox"
+                  checked={adminGeneralSecurityContainer.state.isHideRestrictedByOwner}
+                  onChange={() => { adminGeneralSecurityContainer.switchIsHideRestrictedByOwner() }}
+                />
+                <label htmlFor="isHideRestrictedByOwner">
+                  <p className="help-block small">{ t('security_setting.page_listing_1_desc') }</p>
+                </label>
+              </div>
+            </div>
+          </div>
+
+          <div className="row mb-5">
+            <strong className="col-xs-3 text-right" dangerouslySetInnerHTML={helpPageListingByGroup} />
+            <div className="col-xs-6 text-left">
+              <div className="checkbox checkbox-success">
+                <input
+                  id="isHideRestrictedByGroup"
+                  type="checkbox"
+                  checked={adminGeneralSecurityContainer.state.isHideRestrictedByGroup}
+                  onChange={() => { adminGeneralSecurityContainer.switchIsHideRestrictedByGroup() }}
+                />
+                <label htmlFor="isHideRestrictedByGroup">
+                  <p className="help-block small">{ t('security_setting.page_listing_2_desc') }</p>
+                </label>
+              </div>
+            </div>
+          </div>
+
+          <div className="row mb-5">
+            <strong className="col-xs-3 text-right"> { t('security_setting.complete_deletion') } </strong>
+            <div className="col-xs-9 text-left">
+              <div className="my-0 btn-group">
+                <div className="dropdown">
+                  <button className="btn btn-default dropdown-toggle w-100" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                    <span className="pull-left">{t(`security_setting.${adminGeneralSecurityContainer.state.currentpageCompleteDeletionAuthority}`)}</span>
+                    <span className="bs-caret pull-right">
+                      <span className="caret" />
+                    </span>
+                  </button>
+                  {/* TODO adjust dropdown after BS4 */}
+                  <ul className="dropdown-menu" role="menu">
+                    <li
+                      key="anyone"
+                      role="presentation"
+                      type="button"
+                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('anyone') }}
+                    >
+                      <a role="menuitem">{ t('security_setting.anyone') }</a>
+                    </li>
+                    <li
+                      key="admin_only"
+                      role="presentation"
+                      type="button"
+                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('admin_only') }}
+                    >
+                      <a role="menuitem">{ t('security_setting.admin_only') }</a>
+                    </li>
+                    <li
+                      key="admin_and_author"
+                      role="presentation"
+                      type="button"
+                      onClick={() => { adminGeneralSecurityContainer.changePageCompleteDeletionAuthority('admin_and_author') }}
+                    >
+                      <a role="menuitem">{ t('security_setting.admin_and_author') }</a>
+                    </li>
+                  </ul>
+                  <p className="help-block small">
+                    { t('security_setting.complete_deletion_explain') }
+                  </p>
+                </div>
+              </div>
+            </div>
+          </div>
+          {/* TODO GW-540 */}
+          <div className="form-group">
+            <div className="col-xs-offset-3 col-xs-6">
+              <input type="hidden" name="_csrf" value={this.props.csrf} />
+              <button type="submit" className="btn btn-primary" onClick={this.putSecuritySetting}>{ t('Update') }</button>
+            </div>
+          </div>
+        </fieldset>
+      </React.Fragment>
+    );
+  }
+
+}
+
+SecuritySetting.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  csrf: PropTypes.string,
+  adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
+};
+
+const SecuritySettingWrapper = (props) => {
+  return createSubscribedElement(SecuritySetting, props, [AppContainer, AdminGeneralSecurityContainer]);
+};
+
+export default withTranslation()(SecuritySettingWrapper);

+ 56 - 1
src/client/js/services/AdminGeneralSecurityContainer.js

@@ -6,7 +6,7 @@ import loggerFactory from '@alias/logger';
 const logger = loggerFactory('growi:security:AdminGeneralSecurityContainer');
 const logger = loggerFactory('growi:security:AdminGeneralSecurityContainer');
 
 
 /**
 /**
- * Service container for admin security page (SecurityManagement.jsx)
+ * Service container for admin security page (SecuritySetting.jsx)
  * @extends {Container} unstated Container
  * @extends {Container} unstated Container
  */
  */
 export default class AdminGeneralSecurityContainer extends Container {
 export default class AdminGeneralSecurityContainer extends Container {
@@ -18,6 +18,11 @@ export default class AdminGeneralSecurityContainer extends Container {
 
 
     this.state = {
     this.state = {
       // TODO GW-583 set value
       // TODO GW-583 set value
+      isWikiModeForced: false,
+      currentRestrictGuestMode: 'deny',
+      currentPageCompleteDeletionAuthority: 'anyone',
+      isHideRestrictedByOwner: true,
+      isHideRestrictedByGroup: true,
       useOnlyEnvVarsForSomeOptions: true,
       useOnlyEnvVarsForSomeOptions: true,
       appSiteUrl: '',
       appSiteUrl: '',
       isLocalEnabled: true,
       isLocalEnabled: true,
@@ -36,6 +41,11 @@ export default class AdminGeneralSecurityContainer extends Container {
 
 
     this.switchIsLocalEnabled = this.switchIsLocalEnabled.bind(this);
     this.switchIsLocalEnabled = this.switchIsLocalEnabled.bind(this);
     this.changeRegistrationMode = this.changeRegistrationMode.bind(this);
     this.changeRegistrationMode = this.changeRegistrationMode.bind(this);
+    this.changeRestrictGuestMode = this.changeRestrictGuestMode.bind(this);
+    this.changePageCompleteDeletionAuthority = this.changePageCompleteDeletionAuthority.bind(this);
+    this.switchIsHideRestrictedByGroup = this.switchIsHideRestrictedByGroup.bind(this);
+    this.switchIsHideRestrictedByOwner = this.switchIsHideRestrictedByOwner.bind(this);
+    this.changePageCompleteDeletionAuthority = this.changePageCompleteDeletionAuthority.bind(this);
   }
   }
 
 
   init() {
   init() {
@@ -50,6 +60,51 @@ export default class AdminGeneralSecurityContainer extends Container {
     return 'AdminGeneralSecurityContainer';
     return 'AdminGeneralSecurityContainer';
   }
   }
 
 
+  /**
+   * Change restrictGuestMode
+   */
+  changeRestrictGuestMode(restrictGuestModeLabel) {
+    this.setState({ currentRestrictGuestMode: restrictGuestModeLabel });
+  }
+
+  /**
+   * Change pageCompleteDeletionAuthority
+   */
+  changePageCompleteDeletionAuthority(pageCompleteDeletionAuthorityLabel) {
+    this.setState({ currentPageCompleteDeletionAuthority: pageCompleteDeletionAuthorityLabel });
+  }
+
+  /**
+   * Switch hideRestrictedByOwner
+   */
+  switchIsHideRestrictedByOwner() {
+    this.setState({ isHideRestrictedByOwner:  !this.state.isHideRestrictedByOwner });
+  }
+
+  /**
+   * Switch hideRestrictedByGroup
+   */
+  switchIsHideRestrictedByGroup() {
+    this.setState({ isHideRestrictedByGroup:  !this.state.isHideRestrictedByGroup });
+  }
+
+
+  /**
+   * Update restrictGuestMode
+   * @memberOf AdminGeneralSecuritySContainer
+   * @return {string} Appearance
+   */
+  async updateGeneralSecuritySetting() {
+    const response = await this.appContainer.apiv3.put('/security-setting/general-setting', {
+      restrictGuestMode: this.state.currentRestrictGuestMode,
+      pageCompleteDeletionAuthority: this.state.currentPageCompleteDeletionAuthority,
+      hideRestrictedByGroup: this.state.isHideRestrictedByGroup,
+      hideRestrictedByOwner: this.state.isHideRestrictedByOwner,
+    });
+    const { securitySettingParams } = response.data;
+    return securitySettingParams;
+  }
+
   /**
   /**
    * Switch local enabled
    * Switch local enabled
    */
    */

+ 0 - 114
src/client/js/services/AdminSecurityContainer.js

@@ -1,114 +0,0 @@
-import { Container } from 'unstated';
-
-import loggerFactory from '@alias/logger';
-
-// eslint-disable-next-line no-unused-vars
-const logger = loggerFactory('growi:services:AdminSecurityContainer');
-
-/**
- * Service container for admin security setting page (SecuritySetting.jsx)
- * @extends {Container} unstated Container
- */
-export default class AdminSecurityContainer extends Container {
-
-  constructor(appContainer) {
-    super();
-
-    this.appContainer = appContainer;
-
-    this.state = {
-      // TODO GW-583 set Data from apiv3
-      currentRestrictGuestMode: appContainer.config.restrictGuestMode,
-      currentpageCompleteDeletionAuthority: appContainer.config.pageCompleteDeletionAuthority,
-      hideRestrictedByOwner: appContainer.config.hideRestrictedByOwner,
-      hideRestrictedByGroup: appContainer.config.hideRestrictedByGroup,
-    };
-
-    this.init();
-
-  }
-
-  /**
-   * Workaround for the mangling in production build to break constructor.name
-   */
-  static getClassName() {
-    return 'AdminSecrityContainer';
-  }
-
-  /**
-   * retrieve security data
-   */
-  async init() {
-    // TODO GW-583 init state by apiv3
-  }
-
-
-  /**
-   * Switch restrictGuestMode
-   */
-  switchRestrictGuestMode(restrictGuestModeLabel) {
-    this.setState({ currentRestrictGuestMode: restrictGuestModeLabel });
-  }
-
-  /**
-   * Switch pageCompleteDeletionAuthority
-   */
-  switchPageCompleteDeletionAuthority(pageCompleteDeletionAuthorityLabel) {
-    this.setState({ currentpageCompleteDeletionAuthority: pageCompleteDeletionAuthorityLabel });
-  }
-
-  /**
-   * Switch hideRestrictedByOwner
-   */
-  switchHideRestrictedByOwner() {
-    this.setState({ hideRestrictedByOwner:  !this.state.hideRestrictedByOwner });
-  }
-
-  /**
-   * Switch hideRestrictedByGroup
-   */
-  switchHideRestrictedByGroup() {
-    this.setState({ hideRestrictedByGroup:  !this.state.hideRestrictedByGroup });
-  }
-
-  /**
-   * Update restrictGuestMode
-   * @memberOf AdminSecurityContainer
-   * @return {string} Appearance
-   */
-  async updateRestrictGuestMode() {
-    const response = await this.appContainer.apiv3.put('/security-setting/guest-mode', {
-      restrictGuestMode: this.state.currentRestrictGuestMode,
-    });
-    const { securitySettingParams } = response.data;
-    return securitySettingParams;
-  }
-
-  /**
-   * Update pageDeletion
-   * @memberOf AdminSecurityContainer
-   * @return {string} pageDeletion
-   */
-  async updatePageCompleteDeletionAuthority() {
-    const response = await this.appContainer.apiv3.put('/security-setting/page-deletion', {
-      pageCompleteDeletionAuthority: this.state.currentPageCompleteDeletionAuthority,
-    });
-    const { securitySettingParams } = response.data;
-    return securitySettingParams;
-  }
-
-  /**
-   * Update function
-   * @memberOf AdminSecucityContainer
-   * @return {string} Functions
-   */
-  async updateSecurityFunction() {
-    const response = await this.appContainer.apiv3.put('/security-setting/function', {
-      hideRestrictedByGroup: this.state.hideRestrictedByGroup,
-      hideRestrictedByOwner: this.state.hideRestrictedByOwner,
-    });
-    const { securitySettingParams } = response.data;
-    return securitySettingParams;
-  }
-
-}

+ 42 - 124
src/server/routes/apiv3/security-setting.js

@@ -12,13 +12,9 @@ const ErrorV3 = require('../../models/vo/error-apiv3');
 
 
 const validator = {
 const validator = {
   // TODO correct validator
   // TODO correct validator
-  guestMode: [
+  generalSetting: [
     body('restrictGuestMode').isString(),
     body('restrictGuestMode').isString(),
-  ],
-  pageDeletion: [
     body('pageCompleteDeletionAuthority').isString(),
     body('pageCompleteDeletionAuthority').isString(),
-  ],
-  function: [
     body('hideRestrictedByOwner').isBoolean(),
     body('hideRestrictedByOwner').isBoolean(),
     body('hideRestrictedByGroup').isBoolean(),
     body('hideRestrictedByGroup').isBoolean(),
   ],
   ],
@@ -36,27 +32,31 @@ const validator = {
  *
  *
  *  components:
  *  components:
  *    schemas:
  *    schemas:
- *      GuestModeParams:
- *        type: object
- *        properties:
- *          restrictGuestMode:
- *            type: string
- *            description: type of restrictGuestMode
- *      PageDeletionParams:
+ *      SecurityParams:
  *        type: object
  *        type: object
- *        properties:
- *          pageCompleteDeletionAuthority:
- *            type: string
- *            description: type of pageDeletionAuthority
- *      HideParams:
- *        type: object
- *        properties:
- *          hideRestrictedByOwner:
- *            type: boolean
- *            description: enable hide by owner
- *          hideRestrictedByGroup:
- *            type: boolean
- *            description: enable hide by group
+ *          GeneralSetting:
+ *            type:object
+ *              GuestModeParams:
+ *                type: object
+ *                properties:
+ *                  restrictGuestMode:
+ *                    type: string
+ *                    description: type of restrictGuestMode
+ *              PageDeletionParams:
+ *                type: object
+ *                properties:
+ *                  pageCompleteDeletionAuthority:
+ *                    type: string
+ *                    description: type of pageDeletionAuthority
+ *              Function:
+ *                type: object
+ *                properties:
+ *                  hideRestrictedByOwner:
+ *                    type: boolean
+ *                    description: enable hide by owner
+ *                  hideRestrictedByGroup:
+ *                    type: boolean
+ *                    description: enable hide by group
  */
  */
 
 
 module.exports = (crowi) => {
 module.exports = (crowi) => {
@@ -69,10 +69,10 @@ module.exports = (crowi) => {
   /**
   /**
    * @swagger
    * @swagger
    *
    *
-   *    /security-setting/guest-mode:
+   *    /security-setting/general-setting:
    *      put:
    *      put:
    *        tags: [SecuritySetting]
    *        tags: [SecuritySetting]
-   *        description: Update restrictGuestMode
+   *        description: Update GeneralSetting
    *        requestBody:
    *        requestBody:
    *          required: true
    *          required: true
    *          content:
    *          content:
@@ -83,113 +83,29 @@ module.exports = (crowi) => {
    *                  restrictGuestMode:
    *                  restrictGuestMode:
    *                    description: type of restrictGuestMode
    *                    description: type of restrictGuestMode
    *                    type: string
    *                    type: string
-   *        responses:
-   *          200:
-   *            description: Succeeded to update restrictGuestMode
-   *            content:
-   *              application/json:
-   *                schema:
-   *                  properties:
-   *                    status:
-   *                      $ref: '#/components/schemas/GuestModeParams'
-   */
-  router.put('/guest-mode', loginRequiredStrictly, adminRequired, csrf, validator.guestMode, ApiV3FormValidator, async(req, res) => {
-    const requestParams = {
-      'security:restrictGuestMode': req.body.restrictGuestMode,
-    };
-
-    try {
-      await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
-      const securitySettingParams = {
-        restrictGuestMode: await crowi.configManager.getConfig('crowi', 'security:restrictGuestMode'),
-      };
-      return res.apiv3({ securitySettingParams });
-    }
-    catch (err) {
-      const msg = 'Error occurred in updating restrict guest mode';
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'update-restrictGuestMode-failed'));
-    }
-  });
-
-  /**
-   * @swagger
-   *
-   *    /security-setting/page-deletion:
-   *      put:
-   *        tags: [SecuritySetting]
-   *        description: Update pageDeletion Setting
-   *        requestBody:
-   *          required: true
-   *          content:
-   *            application/json:
-   *              schema:
-   *                type: object
-   *                properties:
-   *                 pageCompleteDeletionAuthority:
-   *                    description: type of pageCompleteDeletionAuthority
+   *                  pageCompleteDeletionAuthority:
    *                    type: string
    *                    type: string
-   *        responses:
-   *          200:
-   *            description: Succeeded to update pageDeletion
-   *            content:
-   *              application/json:
-   *                schema:
-   *                  properties:
-   *                    status:
-   *                      $ref: '#/components/schemas/PageDeletionParams'
-   */
-  router.put('/page-deletion', loginRequiredStrictly, adminRequired, csrf, validator.pageDeletion, ApiV3FormValidator, async(req, res) => {
-    const requestParams = {
-      'security:pageCompleteDeletionAuthority': req.body.pageCompleteDeletionAuthority,
-    };
-
-    try {
-      await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
-      const securitySettingParams = {
-        pageCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageCompleteDeletionAuthority'),
-      };
-      return res.apiv3({ securitySettingParams });
-    }
-    catch (err) {
-      const msg = 'Error occurred in updating page-deletion-setting';
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'update-page-deletion-setting-failed'));
-    }
-  });
-
-  /**
-   * @swagger
-   *
-   *    /security-setting/function:
-   *      put:
-   *        tags: [SecuritySetting]
-   *        description: Update function
-   *        requestBody:
-   *          required: true
-   *          content:
-   *            application/json:
-   *              schema:
-   *                type: object
-   *                properties:
+   *                    description: type of pageDeletionAuthority
    *                  hideRestrictedByOwner:
    *                  hideRestrictedByOwner:
-   *                    description: is enabled hideRestrictedByOwner
    *                    type: boolean
    *                    type: boolean
-   *                  ihideRestrictedByGroup:
-   *                    description: is enabled hideRestrictedBygroup
+   *                    description: enable hide by owner
+   *                  hideRestrictedByGroup:
    *                    type: boolean
    *                    type: boolean
+   *                    description: enable hide by group
    *        responses:
    *        responses:
    *          200:
    *          200:
-   *            description: Succeeded to update function
+   *            description: Succeeded to update general Setting
    *            content:
    *            content:
    *              application/json:
    *              application/json:
    *                schema:
    *                schema:
    *                  properties:
    *                  properties:
    *                    status:
    *                    status:
-   *                      $ref: '#/components/schemas/HideParams'
+   *                      $ref: '#/components/schemas/SecurityParams/GeneralSetting'
    */
    */
-  router.put('/function', loginRequiredStrictly, adminRequired, csrf, validator.function, ApiV3FormValidator, async(req, res) => {
+  router.put('/general-setting', loginRequiredStrictly, adminRequired, csrf, validator.generalSetting, ApiV3FormValidator, async(req, res) => {
     const requestParams = {
     const requestParams = {
+      'security:restrictGuestMode': req.body.restrictGuestMode,
+      'security:pageCompleteDeletionAuthority': req.body.pageCompleteDeletionAuthority,
       'security:list-policy:hideRestrictedByOwner': req.body.hideRestrictedByOwner,
       'security:list-policy:hideRestrictedByOwner': req.body.hideRestrictedByOwner,
       'security:list-policy:hideRestrictedByGroup': req.body.hideRestrictedByGroup,
       'security:list-policy:hideRestrictedByGroup': req.body.hideRestrictedByGroup,
     };
     };
@@ -197,15 +113,17 @@ module.exports = (crowi) => {
     try {
     try {
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
       await crowi.configManager.updateConfigsInTheSameNamespace('crowi', requestParams);
       const securitySettingParams = {
       const securitySettingParams = {
+        restrictGuestMode: await crowi.configManager.getConfig('crowi', 'security:restrictGuestMode'),
+        pageCompleteDeletionAuthority: await crowi.configManager.getConfig('crowi', 'security:pageCompleteDeletionAuthority'),
         hideRestrictedByOwner: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByOwner'),
         hideRestrictedByOwner: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByOwner'),
-        hideRestrictedByGroup: await crowi.configManager.getConfig('crowi', 'customize:security:list-policy:hideRestrictedByGroup'),
+        hideRestrictedByGroup: await crowi.configManager.getConfig('crowi', 'security:list-policy:hideRestrictedByGroup'),
       };
       };
       return res.apiv3({ securitySettingParams });
       return res.apiv3({ securitySettingParams });
     }
     }
     catch (err) {
     catch (err) {
-      const msg = 'Error occurred in updating function';
+      const msg = 'Error occurred in updating security setting';
       logger.error('Error', err);
       logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'update-function-failed'));
+      return res.apiv3Err(new ErrorV3(msg, 'update-secuirty-setting failed'));
     }
     }
   });
   });