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

[Authorized] fix props cannot be delivered if target is a react element (#3813)

何乐 пре 6 година
родитељ
комит
090e1840fa

+ 14 - 33
src/components/Authorized/CheckPermissions.js

@@ -2,21 +2,13 @@ import React from 'react';
 import PromiseRender from './PromiseRender';
 import { CURRENT } from './renderAuthorize';
 
-function isPromise(obj) {
-  return (
-    !!obj &&
-    (typeof obj === 'object' || typeof obj === 'function') &&
-    typeof obj.then === 'function'
-  );
-}
-
 /**
  * 通用权限检查方法
  * Common check permissions method
- * @param { 权限判定 Permission judgment type string |array | Promise | Function } authority
- * @param { 你的权限 Your permission description  type:string} currentAuthority
- * @param { 通过的组件 Passing components } target
- * @param { 未通过的组件 no pass components } Exception
+ * @param { 权限判定 | Permission judgment } authority
+ * @param { 你的权限 | Your permission description } currentAuthority
+ * @param { 通过的组件 | Passing components } target
+ * @param { 未通过的组件 | no pass components } Exception
  */
 const checkPermissions = (authority, currentAuthority, target, Exception) => {
   // 没有判定权限.默认查看所有
@@ -26,47 +18,36 @@ const checkPermissions = (authority, currentAuthority, target, Exception) => {
   }
   // 数组处理
   if (Array.isArray(authority)) {
-    if (authority.indexOf(currentAuthority) >= 0) {
-      return target;
-    }
     if (Array.isArray(currentAuthority)) {
-      for (let i = 0; i < currentAuthority.length; i += 1) {
-        const element = currentAuthority[i];
-        if (authority.indexOf(element) >= 0) {
-          return target;
-        }
+      if (currentAuthority.some(item => authority.includes(item))) {
+        return target;
       }
+    } else if (authority.includes(currentAuthority)) {
+      return target;
     }
     return Exception;
   }
-
   // string 处理
   if (typeof authority === 'string') {
-    if (authority === currentAuthority) {
-      return target;
-    }
     if (Array.isArray(currentAuthority)) {
-      for (let i = 0; i < currentAuthority.length; i += 1) {
-        const element = currentAuthority[i];
-        if (authority === element) {
-          return target;
-        }
+      if (currentAuthority.some(item => authority === item)) {
+        return target;
       }
+    } else if (authority === currentAuthority) {
+      return target;
     }
     return Exception;
   }
-
   // Promise 处理
-  if (isPromise(authority)) {
+  if (authority instanceof Promise) {
     return <PromiseRender ok={target} error={Exception} promise={authority} />;
   }
-
   // Function 处理
   if (typeof authority === 'function') {
     try {
       const bool = authority(currentAuthority);
       // 函数执行后返回值是 Promise
-      if (isPromise(bool)) {
+      if (bool instanceof Promise) {
         return <PromiseRender ok={target} error={Exception} promise={bool} />;
       }
       if (bool) {

+ 18 - 8
src/components/Authorized/PromiseRender.js

@@ -1,7 +1,9 @@
-import React from 'react';
 import { Spin } from 'antd';
+import isEqual from 'lodash/isEqual';
+import React from 'react';
+import { isComponentClass } from './Secured';
 
-export default class PromiseRender extends React.PureComponent {
+export default class PromiseRender extends React.Component {
   state = {
     component: null,
   };
@@ -10,10 +12,14 @@ export default class PromiseRender extends React.PureComponent {
     this.setRenderComponent(this.props);
   }
 
-  componentDidUpdate(nextProps) {
-    // new Props enter
-    this.setRenderComponent(nextProps);
-  }
+  shouldComponentUpdate = (nextProps, nextState) => {
+    const { component } = this.state;
+    if (!isEqual(nextProps, this.props)) {
+      this.setRenderComponent(nextProps);
+    }
+    if (nextState.component !== component) return true;
+    return false;
+  };
 
   // set render Component : ok or error
   setRenderComponent(props) {
@@ -37,8 +43,12 @@ export default class PromiseRender extends React.PureComponent {
   // Authorized  render is already instantiated, children is no instantiated
   // Secured is not instantiated
   checkIsInstantiation = target => {
-    if (!React.isValidElement(target)) {
-      return target;
+    if (isComponentClass(target)) {
+      const Target = target;
+      return props => <Target {...props} />;
+    }
+    if (React.isValidElement(target)) {
+      return props => React.cloneElement(target, props);
     }
     return () => target;
   };

+ 19 - 7
src/components/Authorized/Secured.js

@@ -1,31 +1,43 @@
 import React from 'react';
 import Exception from '../Exception';
 import CheckPermissions from './CheckPermissions';
+
 /**
  * 默认不能访问任何页面
  * default is "NULL"
  */
 const Exception403 = () => <Exception type="403" />;
 
+export const isComponentClass = component => {
+  if (!component) return false;
+  const proto = Object.getPrototypeOf(component);
+  if (proto === React.Component || proto === Function.prototype) return true;
+  return isComponentClass(proto);
+};
+
 // Determine whether the incoming component has been instantiated
 // AuthorizedRoute is already instantiated
 // Authorized  render is already instantiated, children is no instantiated
 // Secured is not instantiated
 const checkIsInstantiation = target => {
-  if (!React.isValidElement(target)) {
-    return target;
+  if (isComponentClass(target)) {
+    const Target = target;
+    return props => <Target {...props} />;
+  }
+  if (React.isValidElement(target)) {
+    return props => React.cloneElement(target, props);
   }
   return () => target;
 };
 
 /**
- * 用于判断是否拥有权限访问此view权限
- * authority 支持传入 string, function:()=>boolean|Promise
- * e.g. 'user' 只有user用户能访问
- * e.g. 'user,admin' user和 admin 都能访问
+ * 用于判断是否拥有权限访问此 view 权限
+ * authority 支持传入 string, () => boolean | Promise
+ * e.g. 'user' 只有 user 用户能访问
+ * e.g. 'user,admin' user 和 admin 都能访问
  * e.g. ()=>boolean 返回true能访问,返回false不能访问
  * e.g. Promise  then 能访问   catch不能访问
- * e.g. authority support incoming string, function: () => boolean | Promise
+ * e.g. authority support incoming string, () => boolean | Promise
  * e.g. 'user' only user user can access
  * e.g. 'user, admin' user and admin can access
  * e.g. () => boolean true to be able to visit, return false can not be accessed