Sfoglia il codice sorgente

Merge pull request #5611 from weseek/imprv/91283-91052-security-setting-ui

imprv: Security Setting UI
Yuki Takei 4 anni fa
parent
commit
1587ba5695

+ 2 - 1
packages/app/resource/locales/en_US/translation.json

@@ -686,7 +686,8 @@
     "max_age": "Max age (msec)",
     "max_age_desc": "Specifies the number (in milliseconds) to expire users session.<br>Default: 2592000000 (30days)",
     "max_age_caution": "Restarting the server is required after you modify this value.",
-    "page_delete_rights_caution": "The \"operation including the descendants\" setting is forced to be stronger than the \"operation for only the selected page\" setting.",
+    "forced_update_desc": "Settings have been forcibly changed. Previous setting: ",
+    "page_delete_rights_caution": "The \"Delete / Delete All\" permission (including descendant pages) is forced to be stronger than the \"Delete / Completely Delete\" permission. <br> <br> Anyone > Admin and autor > Admin only",
     "Authentication mechanism settings": "Authentication Mechanism Settings",
     "setup_is_not_yet_complete": "Setup is not yet complete",
     "alert_siteUrl_is_not_set": "'Site URL' is NOT set. Set it from the {{link}}",

+ 2 - 1
packages/app/resource/locales/ja_JP/translation.json

@@ -685,7 +685,8 @@
     "max_age": "有効期間 (ミリ秒)",
     "max_age_desc": "ユーザーのセッション情報の有効期間をミリ秒で指定できます。<br>デフォルト値: 2592000000 (30日間)",
     "max_age_caution": "この値を変更した後は、サーバーを再起動する必要があります。",
-    "page_delete_rights_caution": "「子孫を含む操作」の設定値は、「単体のみの操作」の設定値よりも強いものに強制されます。",
+    "forced_update_desc": "設定が強制変更されました。前回の設定: ",
+    "page_delete_rights_caution": "「(子孫ページを含む)ゴミ箱に入れる操作 / 完全に削除する」の権限は、「ゴミ箱に入れる操作 / 完全に削除する」よりも強い権限になるように強制されます。 <br><br> 誰でも可能 > 管理者とページ作者が可能 > 管理者のみ可能",
     "Authentication mechanism settings": "認証機構設定",
     "setup_is_not_yet_complete":"セットアップはまだ完了してません",
     "alert_siteUrl_is_not_set": "'サイトURL' が設定されていません。{{link}} から設定してください。",

+ 2 - 1
packages/app/resource/locales/zh_CN/translation.json

@@ -644,7 +644,8 @@
     "max_age": "有效期间  (msec)",
     "max_age_desc": "指定使用户会话过期的数量(以毫秒为单位)。<br>默认值: 2592000000 (30天)",
     "max_age_caution": "修改该值后需要重启服务器。",
-    "page_delete_rights_caution": "\"包括后代的操作\" 的设置被迫强于 \"只对选定的页面进行操作\" 的设置。",
+    "forced_update_desc": "设置已被强行更改。以前的设置: ",
+    "page_delete_rights_caution": "\"删除/全部删除\"权限(包括后代页面)被强制强于\"删除/完全删除\"权限。 <br> <br> 任何人 > 管理员|作者 > 仅管理员",
 		"Authentication mechanism settings": "身份验证机制设置",
 		"setup_is_not_yet_complete": "安装尚未完成",
 		"alert_siteUrl_is_not_set": "主页URL未设置,通过 {{link}} 设置",

+ 23 - 4
packages/app/src/client/services/AdminGeneralSecurityContainer.js

@@ -30,6 +30,8 @@ export default class AdminGeneralSecurityContainer extends Container {
       currentPageRecursiveDeletionAuthority: PageRecursiveDeleteConfigValue.Inherit,
       currentPageCompleteDeletionAuthority: PageSingleDeleteCompConfigValue.AdminOnly,
       currentPageRecursiveCompleteDeletionAuthority: PageRecursiveDeleteCompConfigValue.Inherit,
+      previousPageRecursiveDeletionAuthority: null,
+      previousPageRecursiveCompleteDeletionAuthority: null,
       expandOtherOptionsForDeletion: false,
       expandOtherOptionsForCompleteDeletion: false,
       isShowRestrictedByOwner: false,
@@ -55,6 +57,8 @@ export default class AdminGeneralSecurityContainer extends Container {
     this.changePageCompleteDeletionAuthority = this.changePageCompleteDeletionAuthority.bind(this);
     this.changePageRecursiveDeletionAuthority = this.changePageRecursiveDeletionAuthority.bind(this);
     this.changePageRecursiveCompleteDeletionAuthority = this.changePageRecursiveCompleteDeletionAuthority.bind(this);
+    this.changePreviousPageRecursiveDeletionAuthority = this.changePreviousPageRecursiveDeletionAuthority.bind(this);
+    this.changePreviousPageRecursiveCompleteDeletionAuthority = this.changePreviousPageRecursiveCompleteDeletionAuthority.bind(this);
 
   }
 
@@ -149,18 +153,33 @@ export default class AdminGeneralSecurityContainer extends Container {
     this.setState({ currentPageRecursiveCompleteDeletionAuthority: val });
   }
 
+  /**
+   * Change previousPageRecursiveDeletionAuthority
+   */
+  changePreviousPageRecursiveDeletionAuthority(val) {
+    this.setState({ previousPageRecursiveDeletionAuthority: val });
+  }
+
+
+  /**
+   * Change previousPageRecursiveCompleteDeletionAuthority
+   */
+  changePreviousPageRecursiveCompleteDeletionAuthority(val) {
+    this.setState({ previousPageRecursiveCompleteDeletionAuthority: val });
+  }
+
   /**
    * Switch ExpandOtherOptionsForDeletion
    */
-  switchExpandOtherOptionsForDeletion() {
-    this.setState({ expandOtherOptionsForDeletion:  !this.state.expandOtherOptionsForDeletion });
+  switchExpandOtherOptionsForDeletion(bool) {
+    this.setState({ expandOtherOptionsForDeletion: bool });
   }
 
   /**
    * Switch ExpandOtherOptionsForDeletion
    */
-  switchExpandOtherOptionsForCompleteDeletion() {
-    this.setState({ expandOtherOptionsForCompleteDeletion:  !this.state.expandOtherOptionsForCompleteDeletion });
+  switchExpandOtherOptionsForCompleteDeletion(bool) {
+    this.setState({ expandOtherOptionsForCompleteDeletion: bool });
   }
 
   /**

+ 95 - 30
packages/app/src/components/Admin/Security/SecuritySetting.jsx

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
 import { Collapse } from 'reactstrap';
 import { withTranslation } from 'react-i18next';
 
-import { validateDeleteConfigs } from '~/utils/page-delete-config';
+import { validateDeleteConfigs, prepareDeleteConfigValuesForCalc } from '~/utils/page-delete-config';
 import { withUnstatedContainers } from '../../UnstatedUtils';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { PageDeleteConfigValue } from '~/interfaces/page-delete-config';
@@ -39,6 +39,20 @@ const getDeletionTypeForT = (deletionType) => {
   }
 };
 
+const getDeleteConfigValueForT = (DeleteConfigValue) => {
+  switch (DeleteConfigValue) {
+    case PageDeleteConfigValue.Anyone:
+    case null:
+      return 'security_setting.anyone';
+    case PageDeleteConfigValue.Inherit:
+      return 'security_setting.inherit';
+    case PageDeleteConfigValue.AdminOnly:
+      return 'security_setting.admin_only';
+    case PageDeleteConfigValue.AdminAndAuthor:
+      return 'security_setting.admin_and_author';
+  }
+};
+
 /**
  * Return true if "deletionType" is DeletionType.RecursiveDeletion or DeletionType.RecursiveCompleteDeletion.
  * @param deletionType Deletion type
@@ -62,9 +76,16 @@ class SecuritySetting extends React.Component {
   constructor(props) {
     super(props);
 
+    // functions
     this.putSecuritySetting = this.putSecuritySetting.bind(this);
     this.getRecursiveDeletionConfigState = this.getRecursiveDeletionConfigState.bind(this);
+    this.previousPageRecursiveAuthorityState = this.previousPageRecursiveAuthorityState.bind(this);
+    this.setPagePreviousRecursiveAuthorityState = this.setPagePreviousRecursiveAuthorityState.bind(this);
+    this.expantDeleteOptionsState = this.expantDeleteOptionsState.bind(this);
+    this.setExpantOtherDeleteOptionsState = this.setExpantOtherDeleteOptionsState.bind(this);
     this.setDeletionConfigState = this.setDeletionConfigState.bind(this);
+
+    // render
     this.renderPageDeletePermission = this.renderPageDeletePermission.bind(this);
     this.renderPageDeletePermissionDropdown = this.renderPageDeletePermissionDropdown.bind(this);
   }
@@ -96,25 +117,67 @@ class SecuritySetting extends React.Component {
     ];
   }
 
+  previousPageRecursiveAuthorityState(deletionType) {
+    const { adminGeneralSecurityContainer } = this.props;
+
+    return isTypeDeletion(deletionType)
+      ? adminGeneralSecurityContainer.state.previousPageRecursiveDeletionAuthority
+      : adminGeneralSecurityContainer.state.previousPageRecursiveCompleteDeletionAuthority;
+  }
+
+  setPagePreviousRecursiveAuthorityState(deletionType, previousState) {
+    const { adminGeneralSecurityContainer } = this.props;
+
+    if (isTypeDeletion(deletionType)) {
+      adminGeneralSecurityContainer.changePreviousPageRecursiveDeletionAuthority(previousState);
+      return;
+    }
+
+    adminGeneralSecurityContainer.changePreviousPageRecursiveCompleteDeletionAuthority(previousState);
+  }
+
+  expantDeleteOptionsState(deletionType) {
+    const { adminGeneralSecurityContainer } = this.props;
+
+    return isTypeDeletion(deletionType)
+      ? adminGeneralSecurityContainer.state.expandOtherOptionsForDeletion
+      : adminGeneralSecurityContainer.state.expandOtherOptionsForCompleteDeletion;
+  }
+
+  setExpantOtherDeleteOptionsState(deletionType, bool) {
+    const { adminGeneralSecurityContainer } = this.props;
+
+    if (isTypeDeletion(deletionType)) {
+      adminGeneralSecurityContainer.switchExpandOtherOptionsForDeletion(bool);
+      return;
+    }
+    adminGeneralSecurityContainer.switchExpandOtherOptionsForCompleteDeletion(bool);
+    return;
+  }
+
   /**
    * Force update deletion config for recursive operation when the deletion config for general operation is updated.
    * @param deletionType Deletion type
    */
   setDeletionConfigState(newState, setState, deletionType) {
-    if (isRecursiveDeletion(deletionType)) {
-      setState(newState);
+    setState(newState);
 
+    if (this.previousPageRecursiveAuthorityState(deletionType) !== null) {
+      this.setPagePreviousRecursiveAuthorityState(deletionType, null);
+    }
+
+    if (isRecursiveDeletion(deletionType)) {
       return;
     }
 
     const [recursiveState, setRecursiveState] = this.getRecursiveDeletionConfigState(deletionType);
-    const shouldForceUpdate = !validateDeleteConfigs(newState, recursiveState);
+
+    const calculableValue = prepareDeleteConfigValuesForCalc(newState, recursiveState);
+    const shouldForceUpdate = !validateDeleteConfigs(calculableValue[0], calculableValue[1]);
     if (shouldForceUpdate) {
-      setState(newState);
       setRecursiveState(newState);
-    }
-    else {
-      setState(newState);
+      this.setPagePreviousRecursiveAuthorityState(deletionType, recursiveState);
+      this.setExpantOtherDeleteOptionsState(deletionType, true);
     }
 
     return;
@@ -133,10 +196,7 @@ class SecuritySetting extends React.Component {
           aria-expanded="true"
         >
           <span className="float-left">
-            {currentState === PageDeleteConfigValue.Inherit && t('security_setting.inherit')}
-            {(currentState === PageDeleteConfigValue.Anyone || currentState == null) && t('security_setting.anyone')}
-            {currentState === PageDeleteConfigValue.AdminOnly && t('security_setting.admin_only')}
-            {currentState === PageDeleteConfigValue.AdminAndAuthor && t('security_setting.admin_and_author')}
+            {t(getDeleteConfigValueForT(currentState))}
           </span>
         </button>
         <div className="dropdown-menu" aria-labelledby="dropdownMenuButton">
@@ -184,20 +244,9 @@ class SecuritySetting extends React.Component {
   }
 
   renderPageDeletePermission(currentState, setState, deletionType, isButtonDisabled) {
-    const { t, adminGeneralSecurityContainer } = this.props;
-
-    const expandOtherOptions = isTypeDeletion(deletionType)
-      ? adminGeneralSecurityContainer.state.expandOtherOptionsForDeletion
-      : adminGeneralSecurityContainer.state.expandOtherOptionsForCompleteDeletion;
+    const { t } = this.props;
 
-    const setExpantOtherOptions = () => {
-      if (isTypeDeletion(deletionType)) {
-        adminGeneralSecurityContainer.switchExpandOtherOptionsForDeletion();
-        return;
-      }
-      adminGeneralSecurityContainer.switchExpandOtherOptionsForCompleteDeletion();
-      return;
-    };
+    const expantDeleteOptionsState = this.expantDeleteOptionsState(deletionType);
 
     return (
       <div key={`page-delete-permission-dropdown-${deletionType}`} className="row">
@@ -223,13 +272,30 @@ class SecuritySetting extends React.Component {
                     type="button"
                     className="btn btn-link p-0 mb-4"
                     aria-expanded="false"
-                    onClick={() => setExpantOtherOptions()}
+                    onClick={() => this.setExpantOtherDeleteOptionsState(deletionType, !expantDeleteOptionsState)}
                   >
-                    <i className={`fa fa-fw fa-arrow-right ${expandOtherOptions ? 'fa-rotate-90' : ''}`}></i>
+                    <i className={`fa fa-fw fa-arrow-right ${expantDeleteOptionsState ? 'fa-rotate-90' : ''}`}></i>
                     { t('security_setting.other_options') }
                   </button>
-                  <Collapse isOpen={expandOtherOptions}>
+                  <Collapse isOpen={expantDeleteOptionsState}>
                     <div className="pb-4">
+                      <p className="card well">
+                        <span className="text-warning">
+                          <i className="icon-info"></i>
+                          {/* eslint-disable-next-line react/no-danger */}
+                          <span dangerouslySetInnerHTML={{ __html: t('security_setting.page_delete_rights_caution') }} />
+                        </span>
+                      </p>
+                      { this.previousPageRecursiveAuthorityState(deletionType) !== null && (
+                        <div className="mb-3">
+                          <strong>
+                            {t('security_setting.forced_update_desc')}
+                          </strong>
+                          <code>
+                            {t(getDeleteConfigValueForT(this.previousPageRecursiveAuthorityState(deletionType)))}
+                          </code>
+                        </div>
+                      )}
                       {this.renderPageDeletePermissionDropdown(currentState, setState, deletionType, isButtonDisabled)}
                     </div>
                   </Collapse>
@@ -368,8 +434,7 @@ class SecuritySetting extends React.Component {
         </div>
 
         <h4>{t('security_setting.page_delete_rights')}</h4>
-        <div className="row mb-4"></div>
-        {/* Render PageDeletePermissionDropdown */}
+        {/* Render PageDeletePermission */}
         {
           [
             [currentPageDeletionAuthority, adminGeneralSecurityContainer.changePageDeletionAuthority, DeletionType.Deletion, false],