原子授权的用法

2018-11-21 10:34:35

在前面我们看到API路由可以绑定功能菜单,然后进行功能授权菜单授权。其实,API路由还提供另一种类型的授权:原子授权

原子授权是基于数据的授权。本章节讲述原子授权的基本概念和用法,更详细内容请参见:Cabloy:原子授权

原子授权与API路由的绑定

核心模块a-base提供了一组API路由,用于集中封装原子相关的功能。比如API路由atom/read,用于读取单条原子数据,其路由配置如下:

node-modules/a-base-sync/backend/src/routes.js

{ method: 'post', path: 'atom/read', controller: atom,
  meta: { right: { type: 'atom', action: 2 } },
},
名称 说明
meta 是路由的元数据,可以指定与中间件相关的参数
right 中间件right的参数
type 授权类型,这里是原子授权
action 需要进行授权验证的原子指令代码

我们不关心用户是否有权限访问这条API路由,而是关心用户是否有权限访问相应的原子数据。这就是功能授权原子授权的区别所在

授权内容

针对原子类型原子指令授权,如以下授权记录

角色 原子类型 原子指令
superuser todo create

资源范围授权

在授权时可以指定权限的资源范围,如以下授权记录

角色 原子类型 原子指令 资源范围
superuser todo read 财务部

角色superuser仅能读取财务部todo数据

授权途径

功能授权一样,原子授权也有三种途径。在这里,也通过初始授权途径,给相关的角色分配合适的初始权限

授权记录

角色 原子类型 原子指令 资源范围
authenticated todo create
authenticated todo write 自己的数据
authenticated todo delete 自己的数据
authenticated todo read 自己的数据
superuser todo read authenticated

授权代码

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

async init(options) {
  if (options.version === 1) {
    // atomClassName
    const atomClassName = 'todo';
    // add role rights
    const roleRights = [
      { roleName: 'authenticated', action: 'create' },
      { roleName: 'authenticated', action: 'write', scopeNames: 0 },
      { roleName: 'authenticated', action: 'delete', scopeNames: 0 },
      { roleName: 'authenticated', action: 'read', scopeNames: 0 },
      { roleName: 'superuser', action: 'read', scopeNames: 'authenticated' },
    ];
    const module = this.ctx.app.meta.modules[this.ctx.module.info.relativeName];
    const atomClass = await this.ctx.meta.atomClass.get({ atomClassName });
    for (const roleRight of roleRights) {
      // role
      const role = await this.ctx.meta.role.get({ roleName: roleRight.roleName });
      // scope
      let scope;
      if (!roleRight.scopeNames) {
        scope = 0;
      } else {
        const roleScope = await this.ctx.meta.role.get({ roleName: roleRight.scopeNames });
        scope = [ roleScope.id ];
      }
      // add role right
      await this.ctx.meta.role.addRoleRight({
        roleId: role.id,
        atomClassId: atomClass.id,
        action: this.ctx.constant.module('a-base').atom.action[roleRight.action] || module.main.meta.base.atoms.todo
          .actions[roleRight.action].code,
        scope,
      });
    }
    ...
  }
}

原子指令菜单

有两个特别的菜单类型:新建原子原子列表,其权限是与原子权限相关联的。比如,当我们配置了todocreateread权限,也就相应的具有了新建todo和查看todo列表这两个菜单项的权限

因此,我们需要按如下方式声明这两类菜单项:

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

const meta = {
  base: {
    ...
    functions: {
      createTodo: {
        title: 'Create Todo',
        scene: 'create',
        autoRight: 1,
        atomClassName: 'todo',
        action: 'create',
        sorting: 1,
        menu: 1,
      },
      listTodo: {
        title: 'Todo List',
        scene: 'list',
        autoRight: 1,
        atomClassName: 'todo',
        action: 'read',
        sorting: 1,
        menu: 1,
      },
      ...
    },
  },
名称 说明
autoRight 设为1,表示是自动权限,与对应的原子权限保持一致
atomClassName 对应的原子类型名称
action 对应的原子指令


评论: