Browse Source

fix: authority covered by routes behind (#5723)

* fix: authority covered by later route

* fix: update code style
pull/5786/head
Ding Yi 6 years ago
committed by 陈帅
parent
commit
1f56b902f3
  1. 25
      src/pages/Authorized.tsx
  2. 41
      src/utils/utils.test.ts
  3. 22
      src/utils/utils.ts

25
src/pages/Authorized.tsx

@ -1,35 +1,14 @@
import React from 'react'; import React from 'react';
import Redirect from 'umi/redirect'; import Redirect from 'umi/redirect';
import { connect } from 'dva'; import { connect } from 'dva';
import pathToRegexp from 'path-to-regexp';
import Authorized from '@/utils/Authorized'; import Authorized from '@/utils/Authorized';
import { ConnectProps, ConnectState, Route, UserModelState } from '@/models/connect'; import { getRouteAuthority } from '@/utils/utils';
import { ConnectProps, ConnectState, UserModelState } from '@/models/connect';
interface AuthComponentProps extends ConnectProps { interface AuthComponentProps extends ConnectProps {
user: UserModelState; user: UserModelState;
} }
const getRouteAuthority = (path: string, routeData: Route[]) => {
let authorities: string[] | string | undefined;
routeData.forEach(route => {
if (route.authority) {
authorities = route.authority;
}
// match prefix
if (pathToRegexp(`${route.path}(.*)`).test(path)) {
// exact match
if (route.path === path) {
authorities = route.authority || authorities;
}
// get children authority recursively
if (route.routes) {
authorities = getRouteAuthority(path, route.routes) || authorities;
}
}
});
return authorities;
};
const AuthComponent: React.FC<AuthComponentProps> = ({ const AuthComponent: React.FC<AuthComponentProps> = ({
children, children,
route = { route = {

41
src/utils/utils.test.ts

@ -1,4 +1,4 @@
import { isUrl } from './utils'; import { isUrl, getRouteAuthority } from './utils';
describe('isUrl tests', (): void => { describe('isUrl tests', (): void => {
it('should return false for invalid and corner case inputs', (): void => { it('should return false for invalid and corner case inputs', (): void => {
@ -35,3 +35,42 @@ describe('isUrl tests', (): void => {
expect(isUrl('https://www.example.com/test/123?foo=bar')).toBeTruthy(); expect(isUrl('https://www.example.com/test/123?foo=bar')).toBeTruthy();
}); });
}); });
describe('getRouteAuthority tests', () => {
it('should return authority for each route', (): void => {
const routes = [
{ path: '/user', name: 'user', authority: ['user'], exact: true },
{ path: '/admin', name: 'admin', authority: ['admin'], exact: true },
];
expect(getRouteAuthority('/user', routes)).toEqual(['user']);
expect(getRouteAuthority('/admin', routes)).toEqual(['admin']);
});
it('should return inherited authority for unconfigured route', (): void => {
const routes = [
{ path: '/nested', authority: ['admin', 'user'], exact: true },
{ path: '/nested/user', name: 'user', exact: true },
];
expect(getRouteAuthority('/nested/user', routes)).toEqual(['admin', 'user']);
});
it('should return authority for configured route', (): void => {
const routes = [
{ path: '/nested', authority: ['admin', 'user'], exact: true },
{ path: '/nested/user', name: 'user', authority: ['user'], exact: true },
{ path: '/nested/admin', name: 'admin', authority: ['admin'], exact: true },
];
expect(getRouteAuthority('/nested/user', routes)).toEqual(['user']);
expect(getRouteAuthority('/nested/admin', routes)).toEqual(['admin']);
});
it('should return authority for substring route', (): void => {
const routes = [
{ path: '/nested', authority: ['user', 'users'], exact: true },
{ path: '/nested/users', name: 'users', authority: ['users'], exact: true },
{ path: '/nested/user', name: 'user', authority: ['user'], exact: true },
];
expect(getRouteAuthority('/nested/user', routes)).toEqual(['user']);
expect(getRouteAuthority('/nested/users', routes)).toEqual(['users']);
});
});

22
src/utils/utils.ts

@ -1,5 +1,6 @@
import { parse } from 'querystring'; import { parse } from 'querystring';
import pathRegexp from 'path-to-regexp'; import pathRegexp from 'path-to-regexp';
import { Route } from '@/models/connect';
/* eslint no-useless-escape:0 import/prefer-default-export:0 */ /* eslint no-useless-escape:0 import/prefer-default-export:0 */
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
@ -37,3 +38,24 @@ export const getAuthorityFromRouter = <T extends { path: string }>(
if (authority) return authority; if (authority) return authority;
return undefined; return undefined;
}; };
export const getRouteAuthority = (path: string, routeData: Route[]) => {
let authorities: string[] | string | undefined;
routeData.forEach(route => {
// match prefix
if (pathRegexp(`${route.path}/(.*)`).test(`${path}/`)) {
if (route.authority) {
authorities = route.authority;
}
// exact match
if (route.path === path) {
authorities = route.authority || authorities;
}
// get children authority recursively
if (route.routes) {
authorities = getRouteAuthority(path, route.routes) || authorities;
}
}
});
return authorities;
};

Loading…
Cancel
Save