提交 d61911af 编写于 作者: 陈帅

rm ant-design-pro

上级 4dc7e737
......@@ -54,15 +54,6 @@ const plugins: IPlugin[] = [
autoAddMenu: true,
},
],
// ...(!process.env.TEST && os.platform() === 'darwin'
// ? {
// dll: {
// include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch'],
// exclude: ['@babel/runtime'],
// },
// hardSource: true,
// }
// : {}),
];
// 针对 preview.pro.ant.design 的 GA 统计代码
......
......@@ -56,7 +56,7 @@
"not ie <= 10"
],
"dependencies": {
"@ant-design/pro-layout": "^4.0.3",
"@ant-design/pro-layout": "^4.1.0",
"@antv/data-set": "^0.10.1",
"antd": "^3.16.1",
"bizcharts": "^3.4.3",
......
import CheckPermissions from './CheckPermissions';
import { IAuthorityType } from './CheckPermissions';
import Secured from './Secured';
import check from './CheckPermissions';
import AuthorizedRoute from './AuthorizedRoute';
import React from 'react';
interface IAuthorizedProps {
authority: IAuthorityType;
noMatch?: React.ReactNode;
}
type IAuthorizedType = React.FunctionComponent<IAuthorizedProps> & {
Secured: typeof Secured;
check: typeof check;
AuthorizedRoute: typeof AuthorizedRoute;
};
const Authorized: React.FunctionComponent<IAuthorizedProps> = ({
children,
authority,
noMatch = null,
}) => {
const childrenRender: React.ReactNode = typeof children === 'undefined' ? null : children;
const dom = CheckPermissions(authority, childrenRender, noMatch);
return <>{dom}</>;
};
export default Authorized as IAuthorizedType;
import React from 'react';
import { Route, Redirect } from 'umi';
import Authorized from './Authorized';
import { IAuthorityType } from './CheckPermissions';
interface IAuthorizedRoutePops {
currentAuthority: string;
component: React.ComponentClass<any, any>;
render: () => React.ReactNode;
redirectPath: string;
authority: IAuthorityType;
}
const AuthorizedRoute: React.SFC<IAuthorizedRoutePops> = ({
component: Component,
render,
authority,
redirectPath,
...rest
}) => (
<Authorized
authority={authority}
noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
>
<Route
{...rest}
render={(props: any) => (Component ? <Component {...props} /> : render(props))}
/>
</Authorized>
);
export default AuthorizedRoute;
import { checkPermissions } from './CheckPermissions';
const target = 'ok';
const error = 'error';
describe('test CheckPermissions', () => {
it('Correct string permission authentication', () => {
expect(checkPermissions('user', 'user', target, error)).toEqual('ok');
});
it('Correct string permission authentication', () => {
expect(checkPermissions('user', 'NULL', target, error)).toEqual('error');
});
it('authority is undefined , return ok', () => {
expect(checkPermissions(null, 'NULL', target, error)).toEqual('ok');
});
it('currentAuthority is undefined , return error', () => {
expect(checkPermissions('admin', null, target, error)).toEqual('error');
});
it('Wrong string permission authentication', () => {
expect(checkPermissions('admin', 'user', target, error)).toEqual('error');
});
it('Correct Array permission authentication', () => {
expect(checkPermissions(['user', 'admin'], 'user', target, error)).toEqual('ok');
});
it('Wrong Array permission authentication,currentAuthority error', () => {
expect(checkPermissions(['user', 'admin'], 'user,admin', target, error)).toEqual('error');
});
it('Wrong Array permission authentication', () => {
expect(checkPermissions(['user', 'admin'], 'guest', target, error)).toEqual('error');
});
it('Wrong Function permission authentication', () => {
expect(checkPermissions(() => false, 'guest', target, error)).toEqual('error');
});
it('Correct Function permission authentication', () => {
expect(checkPermissions(() => true, 'guest', target, error)).toEqual('ok');
});
it('authority is string, currentAuthority is array, return ok', () => {
expect(checkPermissions('user', ['user'], target, error)).toEqual('ok');
});
it('authority is string, currentAuthority is array, return ok', () => {
expect(checkPermissions('user', ['user', 'admin'], target, error)).toEqual('ok');
});
it('authority is array, currentAuthority is array, return ok', () => {
expect(checkPermissions(['user', 'admin'], ['user', 'admin'], target, error)).toEqual('ok');
});
it('Wrong Function permission authentication', () => {
expect(checkPermissions(() => false, ['user'], target, error)).toEqual('error');
});
it('Correct Function permission authentication', () => {
expect(checkPermissions(() => true, ['user'], target, error)).toEqual('ok');
});
it('authority is undefined , return ok', () => {
expect(checkPermissions(null, ['user'], target, error)).toEqual('ok');
});
});
import React from 'react';
// eslint-disable-next-line import/no-cycle
import PromiseRender from './PromiseRender';
import { CURRENT } from './renderAuthorize';
export type IAuthorityType =
| string
| string[]
| Promise<any>
| ((currentAuthority: string | string[]) => IAuthorityType);
/**
* 通用权限检查方法
* Common check permissions method
* @param { 权限判定 | Permission judgment } authority
* @param { 你的权限 | Your permission description } currentAuthority
* @param { 通过的组件 | Passing components } target
* @param { 未通过的组件 | no pass components } Exception
*/
const checkPermissions = (
authority: IAuthorityType,
currentAuthority: string | string[],
target: React.ComponentClass<any, any> | React.ReactNode,
Exception: React.ReactNode,
): React.ReactNode => {
// 没有判定权限.默认查看所有
// Retirement authority, return target;
if (!authority) {
return target;
}
// 数组处理
if (Array.isArray(authority)) {
if (Array.isArray(currentAuthority)) {
if (currentAuthority.some(item => authority.includes(item))) {
return target;
}
} else if (authority.includes(currentAuthority)) {
return target;
}
return Exception;
}
// string 处理
if (typeof authority === 'string') {
if (Array.isArray(currentAuthority)) {
if (currentAuthority.some(item => authority === item)) {
return target;
}
} else if (authority === currentAuthority) {
return target;
}
return Exception;
}
// Promise 处理
if (authority instanceof Promise) {
return <PromiseRender ok={target} error={Exception} promise={authority} />;
}
// Function 处理
if (typeof authority === 'function') {
try {
const bool = authority(currentAuthority);
// 函数执行后返回值是 Promise
if (bool instanceof Promise) {
return <PromiseRender ok={target} error={Exception} promise={bool} />;
}
if (bool) {
return target;
}
return Exception;
} catch (error) {
throw error;
}
}
throw new Error('unsupported parameters');
};
export { checkPermissions };
const check = (
authority: IAuthorityType,
target: React.ComponentClass<any, any> | React.ReactNode,
Exception: React.ReactNode,
): React.ReactNode => checkPermissions(authority, CURRENT, target, Exception);
export default check;
import { Spin } from 'antd';
import isEqual from 'lodash/isEqual';
import React from 'react';
// eslint-disable-next-line import/no-cycle
import { isComponentClass } from './Secured';
interface IPromiseRenderProps {
ok: React.ReactNode;
error: React.ReactNode;
promise: Promise<any>;
}
interface IPromiseRenderState {
component: React.ComponentClass<any, any> | React.FunctionComponent<any>;
}
export default class PromiseRender extends React.Component<
IPromiseRenderProps,
IPromiseRenderState
> {
state: IPromiseRenderState = {
component: () => null,
};
componentDidMount() {
this.setRenderComponent(this.props);
}
shouldComponentUpdate = (nextProps: IPromiseRenderProps, nextState: IPromiseRenderState) => {
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: IPromiseRenderProps) {
const ok = this.checkIsInstantiation(props.ok);
const error = this.checkIsInstantiation(props.error);
props.promise
.then(() => {
this.setState({
component: ok,
});
})
.catch(() => {
this.setState({
component: error,
});
});
}
// 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
checkIsInstantiation = (
target: React.ReactNode | React.ComponentClass<any, any>,
): React.FunctionComponent<any> => {
if (isComponentClass(target)) {
const Target = target as React.ComponentClass<any, any>;
return (props: any) => <Target {...props} />;
}
if (React.isValidElement(target)) {
return (props: any) => React.cloneElement(target, props);
}
return () => target as (React.ReactNode & null);
};
render() {
const { component: Component } = this.state;
const { ok, error, promise, ...rest } = this.props;
return Component ? (
<Component {...rest} />
) : (
<div
style={{
width: '100%',
height: '100%',
margin: 'auto',
paddingTop: 50,
textAlign: 'center',
}}
>
<Spin size="large" />
</div>
);
}
}
import React from 'react';
import CheckPermissions from './CheckPermissions';
/**
* 默认不能访问任何页面
* default is "NULL"
*/
const Exception403 = () => 403;
export const isComponentClass = (
component: React.ComponentClass<any, any> | React.ReactNode,
): boolean => {
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: React.ComponentClass<any, any> | React.ReactNode) => {
if (isComponentClass(target)) {
const Target = target as React.ComponentClass<any, any>;
return (props: any) => <Target {...props} />;
}
if (React.isValidElement(target)) {
return (props: any) => React.cloneElement(target, props);
}
return () => target;
};
/**
* 用于判断是否拥有权限访问此 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, () => 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
* e.g. Promise then can not access the visit to catch
* @param {string | function | Promise} authority
* @param {ReactNode} error 非必需参数
*/
const authorize = (authority: string, error?: React.ReactNode) => {
/**
* conversion into a class
* 防止传入字符串时找不到staticContext造成报错
* String parameters can cause staticContext not found error
*/
let classError: boolean | React.FunctionComponent<any> = false;
if (error) {
classError = (() => error) as React.FunctionComponent<any>;
}
if (!authority) {
throw new Error('authority is required');
}
return function decideAuthority(target: React.ComponentClass<any, any> | React.ReactNode) {
const component = CheckPermissions(authority, target, classError || Exception403);
return checkIsInstantiation(component);
};
};
export default authorize;
import Authorized from './Authorized';
import AuthorizedRoute from './AuthorizedRoute';
import Secured from './Secured';
import check from './CheckPermissions';
import renderAuthorize from './renderAuthorize';
Authorized.Secured = Secured;
Authorized.AuthorizedRoute = AuthorizedRoute;
Authorized.check = check;
const RenderAuthorize = renderAuthorize(Authorized);
export default RenderAuthorize;
/* eslint-disable import/no-mutable-exports */
let CURRENT: string | string[] = 'NULL';
/**
* use authority or getAuthority
* @param {string|()=>String} currentAuthority
*/
const renderAuthorize = (Authorized: any) => (
currentAuthority: string | string[] | (() => typeof CURRENT),
) => {
if (currentAuthority) {
if (typeof currentAuthority === 'function') {
CURRENT = currentAuthority();
}
if (
Object.prototype.toString.call(currentAuthority) === '[object String]' ||
Array.isArray(currentAuthority)
) {
CURRENT = currentAuthority as string[];
}
} else {
CURRENT = 'NULL';
}
return Authorized;
};
export { CURRENT };
export default (Authorized: any) => renderAuthorize(Authorized);
......@@ -10,6 +10,7 @@ import {
BasicLayoutProps as BasicLayoutComponentsProps,
MenuDataItem,
Settings,
SettingDrawer,
} from '@ant-design/pro-layout';
export interface BasicLayoutProps extends BasicLayoutComponentsProps, ConnectProps {
......@@ -39,21 +40,25 @@ const BasicLayout: React.FC<BasicLayoutProps> = props => {
dispatch!({ type: 'global/changeLayoutCollapsed', payload });
return (
<BasicLayoutComponents
formatMessage={formatMessage}
logo={logo}
onChangeSetting={settings =>
dispatch!({
type: 'settings/changeSetting',
payload: settings,
})
}
onChangeLayoutCollapsed={handleMenuCollapse}
renderRightContent={RightProps => <RightContent {...RightProps} />}
{...props}
>
{children}
</BasicLayoutComponents>
<>
<BasicLayoutComponents
logo={logo}
onCollapse={handleMenuCollapse}
rightContentRender={RightProps => <RightContent {...RightProps} />}
{...props}
>
{children}
</BasicLayoutComponents>
<SettingDrawer
settings={props.settings}
onSettingChange={settings =>
dispatch!({
type: 'settings/changeSetting',
payload: settings,
})
}
/>
</>
);
};
......
import { Authorized as RenderAuthorized } from 'ant-design-pro';
import { default as RenderAuthorized } from '@/components/Authorized';
import { getAuthority } from './authority';
let Authorized = RenderAuthorized(getAuthority()); // eslint-disable-line
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册