Skip to content

umi-plugin-access-code 权限code插件

基于umi框架体系编写的一个帮助开发人员管理权限code的插件

在实际的开发过程中。你总是会需要处理关于路由级别甚至是按钮级别、数据级别的权限。 针对这个问题。UMI有提供一个开箱即用的权限插件

当你需要配置路由权限。你只需要再路由中加上access参数.像这样

typescript
// config/route.ts
export const routes =  [
  {
    path: '/pageA',
    component: 'PageA',
    access: 'canReadPageA', // 权限定义返回值的某个 key
  }
]

ps: 你需要同时在src/access.ts同时声明这个canReadPageA为false

如果你需要关联按钮权限。上述的链接也提供的相应的方案去解决。

看起来 umi的插件已经能够满足我们的要求了。那为什么还会有umi-plugin-access-code插件呢?

动机(motive)

让我们来看一下关于权限code绑定交互实际开发的流程

  • 开发人员手动在路由上绑定 access。 就像上面那样。并且在 src/access.ts 种声明权限code
  • (可选)如果有按钮级别权限。你需要在src/access.ts也预先定义好
  • 将你所有的code在资源管理页面中一个!一个!一个!的手动进行创建。并给他们起好名字.像这样 1

如果你的后管项目只有三五个页面。这个工作或许看起来并不是什么大问题。但是,如果你的项目存在五十六甚至七八十个页面。那么这个工作多少是有那么些枯燥与乏味。

试想一下。这个工作不仅需要花费你大量的时间。如果你创建过程中还创建错了,那么它也会相当的考验你的耐心。

程序员的宗旨是:能够自动化的东西。一律不用手写。为了在权限code管理维护上实现这个目标。umi-plugin-access-code 诞生了。

使用

首先声明。umi-plugin-access-code并没有独立于umi的权限管理另起炉灶。依然是在它的权限模式下去减少上面我们提到的开发人员的工作量。如果你不愿意使用。你依然可以无缝的切换到最初的模式。

这个插件默认内置到框架中并且默认启动了。

你可以在package.json中找到这个依赖。并且在config/config.ts中看到插件相关的配置

typescript
// ...ignore others
accessCodes: {
    routeInject: REACT_APP_ENV !== 'dev',
    exclude: ['home', 'login', 'user-setting', 'user-notices', 'sysSetting-resourcesManagement'],
    sql: true
  },

运行

在项目目录下运行命令

bash
yann|pnpm code

当你运行命令 yarn code 时,这将会在src/access.ts中根据路由路径以及额外信息。生成所有的access code。并且会有一段CODE_START的标注。像这样:

2

CODE_START 与 CODE_END 中的内容都是自动生成的。请不要修改或者在里面写入任何内容。因为他会在你重新运行 yarn code 时覆盖掉!!

并且如果你的sql设置为true。会同时在src目录下生成一份access.sql文件。下面我们也会详细解释

配置参数

这个插件很简单。只有三个参数配置。接下来我们挨个介绍

routeInejct 路由注入

上面我们提到。如果你需要配置路由级的权限。那你就要在路由上写上access: xxx来绑定对应的code。所以首先就通过 routeInejct 配置来解决这里的手动编写的问题

让我们来举个例子。让你直观的理解这个过程。假设我们有这么一个路由

typescript
// config/route.ts
export const routes =  [
  {
    path: '/page',
    component: 'Page',
    access: 'page', // 权限定义返回值的某个 key
    children: [{
       path: '/page/child',
       component: 'Page/child',
       access: 'pageChild', // 权限定义返回值的某个 key
    }]
  }
]

我们发现。我们完全可以将access的值按照特殊的规则(即:组合path,删除斜杠并且子级首字母大写的方式)来定义。这样既直观。而且也非常可靠好记。

既然有这种规律的模式。那我们是不是可以将这个行为自动化? 所以。当你设置 routeInejct: true时。那么在项目启动编译时。我们可以动态的改写运行时路由代码。将access参数按照特定的规则动态写入。这样你就不用手动的一个一个的编写access参数了

typescript
// config/route.ts
export const routes =  [
  {
    path: '/page',
    component: 'Page',
    // access: 'page', // 不用写了。插件会帮你写上
    children: [{
       path: '/page/child',
       component: 'Page/child',
      //  access: 'pageChild', // 不用写了。插件会帮你写上
    }]
  }
]

事实上。我们设置的是 routeInject: REACT_APP_ENV !== 'dev'。表示开发环境时不注入。所有权限都会开放。这样方便开发工作

exclude 排除

有了上面的例子。我们知道。所有的path都会被绑定access参数。但是有些公共页面。比如登录注册等不需要绑定权限的路由页面也会被关联照顾。为了解决误伤的问题。你可以通过exclude参数。传递不需要绑定的code.

注意排除的是 code 不是 path

sql

上面的操作。我们解决了手动编写路由表中 accesssrc/access.ts这两处的工作。那么。在资源管理页面手动创建code的工作。我们还没解决。所以,这个配置参数就是用来解决这最后问题的。

当你设置sql: true时。 运行 yarn code 会在src/access.ts中生成一份code。同时会在同级下生成一份access.sql脚本文件。

此时你可以将这份脚本文件提供给后端同学。让他在数据库中运行一下。 这时候。你再去刷新一下资源管理页面。 你会惊奇的发现。所有的资源都已经创建好了。并且帮你正确的关联了父子级关系!

按钮级权限绑定

有时候你不仅只是需要绑定菜单路由权限。业务需要更加细粒度的控制。比如说到按钮基本的操作权限。此时,我们就需要扩展这一需求。如何来做呢?

其实也非常简单。我们只需要在页面路由中加入operationAccess扩展参数即可。

ts
export default [
  {
    name: '基础设置',
    path: '/basicSetting',
    routes: [
      {
        name: '素材库',
        path: '/basicSetting/materialLibrary',
        component: './basicSetting/materialLibrary',
        // 按钮级权限绑定
        operationAccess: [
          {name:'新增', code: 'add'},
          {name:'编辑', code: 'edit'},
          {name:'删除', code: 'delete'},
          {name:'查看', code: 'view'}
        ]
      }
    ]
  }
]

上面的示例最终会在路径的基础上扩展出四个按钮权限code。并帮你完成注入。

ts
// src/access.ts
export const codes = [
  'basicSetting',
  'basicSetting-materialLibrary',
  'basicSetting-materialLibrary-add',
  'basicSetting-materialLibrary-edit',
  'basicSetting-materialLibrary-delete',
  'basicSetting-materialLibrary-view',
]

当然按钮的权限 你依然需要配合UMI框架中的 <Access> 组件或者 useAccesshook来使用

结尾

至此。本插件的使用与实现细节。都已经完全讲完了。正如开头所说。他只是帮助你解决开发效率问题的。如果你不喜欢。你完全可以回到手动的模式。按照umi提供的文档去管理你的权限