diff --git a/src/pages/Authorized.tsx b/src/pages/Authorized.tsx index 9c94e479..e01e3aba 100644 --- a/src/pages/Authorized.tsx +++ b/src/pages/Authorized.tsx @@ -1,35 +1,14 @@ import React from 'react'; import Redirect from 'umi/redirect'; import { connect } from 'dva'; -import pathToRegexp from 'path-to-regexp'; 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 { 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 = ({ children, route = { diff --git a/src/utils/utils.test.ts b/src/utils/utils.test.ts index c2bb32dc..ea848193 100644 --- a/src/utils/utils.test.ts +++ b/src/utils/utils.test.ts @@ -1,4 +1,4 @@ -import { isUrl } from './utils'; +import { isUrl, getRouteAuthority } from './utils'; describe('isUrl tests', (): 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(); }); }); + +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']); + }); +}); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 9476d6d7..b9ce15df 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,5 +1,6 @@ import { parse } from 'querystring'; import pathRegexp from 'path-to-regexp'; +import { Route } from '@/models/connect'; /* 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]*))?)$/; @@ -37,3 +38,24 @@ export const getAuthorityFromRouter = ( if (authority) return authority; 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; +};