Skip to content

数据权限

在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。

TIP

超级管理员管理员 admin 拥有所有数据权限(userId=1)

默认角色拥有所有数据权限(如不需要数据权限不用设置数据权限操作)

数据权限设置

在(系统管理-角色管理)设置需要数据权限的角色 目前支持以下几种权限:

  • 全部数据权限
  • 自定数据权限
  • 部门数据权限
  • 部门及以下数据权限
  • 仅本人数据权限

数据权限实现

实现数据权限实际就是在数据查询的 sql 语句中添加 where 条件,例如:

用户管理(未过滤数据权限的情况)

sql
select u.*
from sys_user u
	left join sys_dept d on u.dept_id = d.dept_id

用户管理(过滤数据权限的情况)

sql
select u.*
from sys_user u
	left join sys_dept d on u.dept_id = d.dept_id
-- 查询本部门的数据
where u.dept_id = 105
sql
select u.*
from sys_user u
	left join sys_dept d on u.dept_id = d.dept_id
 -- 查询本部门及以下数据权限
where u.dept_id in(
	select dept_id from sys_dept where dept_id = 100 or FIND_IN_SET(100, ancestors)
)

所以只需根据当前登录的用户分配的数据权限类型,动态生成不同的数据范围 sql 语句,然后拼接到查询 sql 中即可实现数据过滤。

数据权限使用

在需要数据权限的方法上添加 @DataScope 装饰器。

  • deptAlias:部门表别名
  • userAlias:用户表别名

TIP

如果是自己的业务表需要实现数据权限,需要有 dept_iduser_id 这两个字段。

在 Controller 层使用

使用 @DataScopeSql 参数装饰器,获取到数据范围 sql 语句。

你需要往下层传递 sql 语句,并且包含数据权限的接口都要添加。

ts
import { DataScope, DataScopeSql } from '@vivy-common/datascope'
export class UserController {
  @DataScope({ deptAlias: 'd', userAlias: 'u' })
  async list(@DataScopeSql() dsSql: string) {
    return await this.userService.list(dsSql)
  }
}
ts
export class UserService {
  async list(dsSql: string) {
    return this.userRepository
      .createQueryBuilder('u')
      .leftJoin('sys_dept', 'd', 'd.dept_id = u.dept_id')
      .andWhere(dsSql)
      .getMany()
  }
}

在 Service 层使用(推荐)

使用 dataScopeService.sql 方法,获取到数据范围 sql 语句。

它从 异步上下文 中获取用户信息,你可以随意调用包含数据权限的方法而无需传递参数。

ts
import { DataScope, DataScopeService } from '@vivy-common/datascope'
export class UserService {
  @DataScope({ deptAlias: 'd', userAlias: 'u' })
  async list() {
    const dsSql = this.dataScopeService.sql(this.list)
    return this.userRepository
      .createQueryBuilder('u')
      .leftJoin('sys_dept', 'd', 'd.dept_id = u.dept_id')
      .andWhere(dsSql)
      .getMany()
  }
}

在 Mapper 层使用(推荐)

Service 层使用方法。Mapper 层是由 Mybatis 插件提供的。

ts
import { DataScope, DataScopeService } from '@vivy-common/datascope'
export class UserMapper {
  @DataScope({ deptAlias: 'd', userAlias: 'u' })
  async list() {
    const dsSql = this.dataScopeService.sql(this.list)
    const sql = this.mybatisService.getSql('user.mapper', 'list', { dsSql })
    return this.dataSource.query(sql)
  }
}
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="user.mapper">
  <select id="list">
    select u.*
    from sys_user u
      left join sys_dept d on u.dept_id = d.dept_id
    where ${dsSql}
  </select>
</mapper>

相关源码