CRM系统前端权限控制优化升级方案
为什么要做权限控制?
当前前端代码中控制组件显示有几种方式:
1. 通过 visible_permissions 接口返回的权限列表
- /profile 接口返回了当前登录用户的基础信息以及一个长长的权限列表
- 有了这个列表以后,就可以在代码里这样去控制组件显示:
1 | const tabs = [ |
开发上线的时候一时爽,但是未来要修改,查阅权限,就会很痛苦。
产品想不起来某个角色是否有某个权限,就来问开发,开发发现这部分代码不是自己写的,就开始全局搜,凭感觉找。找到后产品说我们要修改一下…
2. 通过 role_id 判断权限
- 这个就更过分了,/profile 接口会返回一个
roles
字段,是一个用逗号分隔的角色组合:roles: "1,3,20"
- 同理在代码里就是这样控制:
1 | const tabs = [ |
这么做就连权限规则的名字也没有,所以更加难整理修改。
原有的两种判断方式都是在代码中写定判断逻辑
- 判断方式不统一且太分散
- 修改某角色的权限组合要改代码逻辑,成本比较大
- 不容易定位到某角色某权限的当前表现
前端权限设计逻辑
分散在项目各处的权限判断必然是错误的方向,想统一去管理页面渲染,最能想到的就是用一个JSON格式的配置告诉页面这个登录用户的页面将会渲染成什么样子。
所以方案就是:
- 为每个角色转一份JSON,并提供一个UI界面去管理控制、修改模板。
- 每个登录用户的权限是他/她拥有的各个角色的合集。
- React:接口给我什么,我就渲染什么。
JSON数据的层级即为前端页面组件的层级,通过遍历数据来渲染应该显示的组件。
JSON的组成为:
1 | pages: [ |
每个对象都拥有:
component_type
React 用于判断渲染的组件类型(Menu / Page / Section …)contents
子集,所包含的层级关系id
idkey
React 用于判断渲染具体组件的 keymeta
其他信息name
中文名称
页面上应该渲染的元素全部由这个数据决定。
拆页面:页面组件和层级定义
- Menu (component_type: menu)
- 侧边栏的大类(主控台、常用功能、管理功能)
- Page(component_type: menu-page/single-page)
- 路由,不同的页面,/dashboard、/workbench、… 等
- 侧边栏的配置项
- 没有权限的路由会返回404界面
- 分为 menu-page(标准页) 和 single-page(详情页)
- Section(component_type:section-group / section)
- 各页面下的标签栏(支持嵌套)
- 必须是 section-group 作为父级,section 作为子级,section-group 下只能是 section,section 下可以继续加入 section-group 来实现嵌套
- 首页组件 (component_type: dashboard-item)
- 首页上按权限显示的组件
- Common
- 任何上面没有提到的其他需要权限的内容
页面层级示意图:
接口设计
- 页面组件可选配置的模板的CRUD
GET
POST
页面组件的模板编辑:
- 各个角色所配的内容的CRUD
GET
POST
角色所拥有的的权限编辑:
- 用户登录后获取的所拥有角色合集的权限配置
GET
/fe_permissions 返回包含当前登录用户的所有页面内容(JSON)
代码实现
提供了一系列内容的 Providers,JSON 配置里给出组件类型,就按需渲染对应的内容。
Components Providers
├── ContentProvider.jsx
├── DashboardProvider.jsx
├── PageProvider.jsx
├── SectionsProvider.jsx
└── index.less
举例:ContentProvider.jsx
1 | const ContentProvider = (props) => { |
SectionProvider.jsx
1 | const SectionsProvider = (props) => { |
在遍历整个JSON配置时渲染对应的组件。