菜单授权的用法

2018-11-20 14:02:07

前面我们实现了一个前后端联动的基本流程,后端提供了一个API路由,前端提供了一个页面组件。本章节,我们准备添加一个菜单,并给菜单赋予相应的权限。当某个具备权限的用户进入系统,可以在首页看到此菜单

功能与菜单

Cabloy是前后端分离的框架。前后端分离对后端路由的权限控制提出了更高的要求。因此,权限的核心就是对后端API路由的权限控制

功能API路由的关系

API路由的目的是向前端提供相应的API服务,在这里我们称之为功能。于是,一个或多个API路由对应一个功能

在实际操作中,是针对功能授权,然后在API路由中指定此路由对应哪个功能,从而实现对API路由的访问控制

功能菜单的关系

菜单属于功能的特例:

  1. 首先,菜单也对应一个或多个API路由,其授权方式与功能一致

  2. 其次,将功能的属性menu设为1,就成为了菜单,同时再给菜单指定一个前端页面组件的路径,就可以在首页显示一个菜单链接了。

声明菜单

每个业务模块有一个meta元数据对象,我们可以在里面声明一个菜单

src/module/test-todo/backend/src/meta.js

const meta = {
  base: {
    ...
    functions: {
      ...
      testEcho: {
        title: 'Test Echo',
        scene: 'tools',
        actionPath: 'test/echo',
        sorting: 1,
        menu: 1,
      },
    },
  },
};
名称 说明
title 菜单标题,如果要支持国际化,可以直接添加对应的语言资源
scene 菜单场景,用于菜单的分类显示
actionPath 前端页面组件路径
sorting 用于显示的排序值
menu 是否为菜单,如果不是菜单就是功能

绑定API路由

src/module/test-todo/backend/src/routes.js

// test
{ method: 'post', path: 'test/echo', controller: test, middlewares: 'transaction,middlewareDemo',
  meta: {
    right: {
      type: 'function',
      name: 'testEcho',
    },
  },
},
名称 说明
meta 是路由的元数据,可以指定与中间件相关的参数
right 中间件right的参数
type 授权类型,这里是功能授权
name 需要进行授权验证的功能名称

菜单授权

Cabloy对菜单授权采用白名单策略,所有授权都必须显式设置

菜单授权有三种途径:

  1. 人工授权:如果某些权限只有在实际部署或运行时才能决定,可通过管理界面进行授权操作
  2. 初始授权:如果需要在系统运行时,预先初始化权限,可以在后端API路由version/init中通过代码分配权限。比如,给角色superuser分配权限
  3. 测试授权:为了测试与开发的便利,还可以在开发阶段预先初始化权限,可以在后端API路由version/test中通过代码分配权限。比如,给某些测试角色分配权限

在这里,我们通过初始授权,给角色superuser分配访问菜单testEcho的权限

src/module/test-todo/backend/src/service/version.js

async init(options) {
  if (options.version === 1) {
    ...
    // roleFunctions
    const role = await this.ctx.meta.role.getSystemRole({ roleName: 'superuser' });
    const functions = [ 'testEcho' ];
    for (const functionName of functions) {
      const func = await this.ctx.meta.function.get({
        name: functionName,
      });
      await this.ctx.meta.role.addRoleFunction({
        roleId: role.id,
        functionId: func.id,
      });
    }
  }
}
名称 说明
options.version 模块数据版本,当模块编译并发布后,模块当前的数据版本建议处于封闭状态。如果有新的数据架构变更,递增数据版本。这样,随着业务模块的升级,模块内部的数据架构也将无缝升级
superuser 内置角色,用户root归属于此角色

重置服务

前面提到模块数据版本的概念。由于在当前版本的开发阶段,需要频繁的修改数据架构,因此,我们需要重置服务,以便让修改的数据架构生效

$ npm run test:backend
$ npm run dev:backend

前面提到,npm run test:backend可以重新创建一个新的测试数据库,而npm run dev:backend则自动寻找刚才新创建的测试数据库,并重启后端服务



评论: