Просмотр исходного кода

fix: authority covered by routes behind (#5723)

* fix: authority covered by later route

* fix: update code style
Ding Yi 6 лет назад
Родитель
Сommit
1f56b902f3
3 измененных файлов с 64 добавлено и 24 удалено
  1. 2 23
      src/pages/Authorized.tsx
  2. 40 1
      src/utils/utils.test.ts
  3. 22 0
      src/utils/utils.ts

+ 2 - 23
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<AuthComponentProps> = ({
   children,
   route = {

+ 40 - 1
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']);
+  });
+});

+ 22 - 0
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 = <T extends { path: string }>(
   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;
+};