From 090e1840fa74226af423d912ac94e313c2b5bb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E4=B9=90?= Date: Fri, 22 Mar 2019 21:51:40 +0800 Subject: [PATCH] [Authorized] fix props cannot be delivered if target is a react element (#3813) --- src/components/Authorized/CheckPermissions.js | 47 ++++++------------- src/components/Authorized/PromiseRender.js | 26 ++++++---- src/components/Authorized/Secured.js | 26 +++++++--- 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/src/components/Authorized/CheckPermissions.js b/src/components/Authorized/CheckPermissions.js index ba83f5b9..4b49d1f8 100644 --- a/src/components/Authorized/CheckPermissions.js +++ b/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 ; } - // Function 处理 if (typeof authority === 'function') { try { const bool = authority(currentAuthority); // 函数执行后返回值是 Promise - if (isPromise(bool)) { + if (bool instanceof Promise) { return ; } if (bool) { diff --git a/src/components/Authorized/PromiseRender.js b/src/components/Authorized/PromiseRender.js index 8e2a4059..58de6593 100644 --- a/src/components/Authorized/PromiseRender.js +++ b/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 => ; + } + if (React.isValidElement(target)) { + return props => React.cloneElement(target, props); } return () => target; }; diff --git a/src/components/Authorized/Secured.js b/src/components/Authorized/Secured.js index c935183d..25b961f0 100644 --- a/src/components/Authorized/Secured.js +++ b/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 = () => ; +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 => ; + } + 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 -- GitLab