在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。
例如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制, 对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了。如设置只能看本公司、或者本部门的数据,对于特殊的领导,可能需要跨部门的数据, 因此程序不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制。

(捐赠版、授权版才有此功能)

数据权限演示

1、创建一个用于测试数据权限的表

CREATE TABLE `demo_data_auth` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT '' COMMENT '标题',
  `created_by` int(10) unsigned DEFAULT '0' COMMENT '创建人',
  `updated_by` int(10) unsigned DEFAULT '0' COMMENT '修改人',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `updated_at` datetime DEFAULT NULL COMMENT '修改时间',
  `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `dept_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建部门',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='数据权限测试';

2、使用代码生成相关逻辑

代码生成请参考:代码生成章节

代码生成->导入上面创建的表后设置一下生成信息:

生成后使用不同用户创建相关数据,此时还没接入数据权限验证,我们稍后接入:

3、添加数据权限判断功能

添加数据权限需要和用户表关联查询

注意数据权限有两种模式,一种是和用户相关连,按创建人ID来划分数据权限,所以业务表里面必须带有created_by字段,否则权限不生效,次模式若用户修改了部门,则数据会跟随用户迁移到新部门,使用方法GetAuthWhere
另一种是部门相关联,使用部门ID来划分数据权限,所以业务表里面需要同时有dept_idcreated_by字段,此模式数据归部门所有,不会跟随用户转移,使用方法GetAuthDeptWhere,请根据实际情况选取

列表页查询权限控制,修改internal/app/demo/logic/demoDataAuth/demo_data_auth.go文件List方法内容:

#修改列表页面
func (s *sDemoDataAuth) List(ctx context.Context, req *model.DemoDataAuthSearchReq) (listRes *model.DemoDataAuthSearchRes, err error) {
    listRes = new(model.DemoDataAuthSearchRes)
    err = g.Try(ctx, func(ctx context.Context) {
        m := dao.DemoDataAuth.Ctx(ctx).WithAll()
        if req.Id != "" {
            m = m.Where(dao.DemoDataAuth.Columns().Id+" = ?", req.Id)
        }
        if req.Title != "" {
            m = m.Where(dao.DemoDataAuth.Columns().Title+" = ?", req.Title)
        }
        if req.CreatedBy != "" {
            m = m.Where(dao.DemoDataAuth.Columns().CreatedBy+" = ?", gconv.Uint(req.CreatedBy))
        }
        if req.CreatedAt != nil && len(req.CreatedAt) > 0 {
            if req.CreatedAt[0] != "" {
                m = m.Where(dao.DemoDataAuth.Columns().CreatedAt+" >= ?", gconv.Time(req.CreatedAt[0]))
            }
            if len(req.CreatedAt) > 1 && req.CreatedAt[1] != "" {
                m = m.Where(dao.DemoDataAuth.Columns().CreatedAt+" < ?", gconv.Time(req.CreatedAt[1]))
            }
        }
        if req.Birthday != nil && len(req.Birthday) > 0 {
            if req.Birthday[0] != "" {
                m = m.Where(dao.DemoDataAuth.Columns().Birthday+" >= ?", gconv.Time(req.Birthday[0]))
            }
            if len(req.Birthday) > 1 && req.Birthday[1] != "" {
                m = m.Where(dao.DemoDataAuth.Columns().Birthday+" < ?", gconv.Time(req.Birthday[1]))
            }
        }
        //数据权限只需添加此行代码
        //注意GetAuthWhere是使用创建人ID,此时若创建人转移了部门,数据会跟随创建人迁移
        //如果要保持数据保留在原部门需要使用部门ID则使用GetAuthDeptWhere
        m = systemService.SysUser().GetAuthWhere(
            ctx,
            m,
            systemService.Context().GetLoginUser(ctx),
        )
        listRes.Total, err = m.Count()
        liberr.ErrIsNil(ctx, err, "获取总行数失败")
        if req.PageNum == 0 {
            req.PageNum = 1
        }
        listRes.CurrentPage = req.PageNum
        if req.PageSize == 0 {
            req.PageSize = consts.PageSize
        }
        order := "id asc"
        if req.OrderBy != "" {
            order = req.OrderBy
        }
        var res []*model.DemoDataAuthListRes
        err = m.Page(req.PageNum, req.PageSize).Order(order).Scan(&res)
        liberr.ErrIsNil(ctx, err, "获取数据失败")
        listRes.List = make([]*model.DemoDataAuthListRes, len(res))
        for k, v := range res {
            listRes.List[k] = &model.DemoDataAuthListRes{
                Id:          v.Id,
                Title:       v.Title,
                CreatedUser: v.CreatedUser,
                CreatedBy:   v.CreatedBy,
                CreatedAt:   v.CreatedAt,
                Birthday:    v.Birthday,
            }
        }
    })
    return
}

在添加数据权限之前,可以看到后端控制台sql日志中的查询语句如下:

SELECT `id`,`title`,`created_by`,`updated_by`,`created_at`,`updated_at`,`deleted_at` FROM `demo_data_auth` WHERE `deleted_at` IS NULL ORDER BY `id` asc LIMIT 0,10

添加数据权限判断后生成的查询语句:

SELECT `id`,`title`,`created_by`,`created_at`,`birthday` FROM `demo_data_auth` WHERE (`created_by`=16) AND `deleted_at` IS NULL ORDER BY `id` asc LIMIT 0,10

生成上面sql语句是因为我当前登录用户数据权限是仅本人数据权限只能查看自己添加的数据,可以看到查询条件中多了条件AND (created_by = 16))

列表页面只能查询出两条数据:

修改一下数据权限为本部门及下级部门权限

修改当前登录用户部门为深圳总公司则他应该能访问所在部门及下级部门添加的数据

列表查询数据:

生成的查询语句:

SELECT `id`,`title`,`created_by`,`created_at`,`birthday` FROM `demo_data_auth` WHERE (`created_by` IN ((SELECT `id` FROM `sys_user` WHERE (`dept_id` IN (102,108,202,203,109)) AND `deleted_at` IS NULL))) AND `deleted_at` IS NULL ORDER BY `id` asc LIMIT 0,10

可以看到查询条件已改变为:AND (created_by in ......))

控制修改操作权限实例如下:

修改internal/app/demo/logic/demoDataAuth/demo_data_auth.go文件Edit方法内容:

func (s *sDemoDataAuth) Edit(ctx context.Context, req *model.DemoDataAuthEditReq) (err error) {
    err = g.Try(ctx, func(ctx context.Context) {
        //添加数据权限判断条件
        var one gdb.Record
        m := dao.DemoDataAuth.Ctx(ctx).WherePri(req.Id)
        //注意GetAuthWhere是使用创建人ID,此时若创建人转移了部门,数据会跟随创建人迁移
        //如果要保持数据保留在原部门需要使用部门ID则使用GetAuthDeptWhere
        m = systemService.SysUser().GetAuthWhere(
            ctx,
            m,
            systemService.Context().GetLoginUser(ctx),
        )
        one, err = m.Fields(dao.DemoDataAuth.Columns().Id).One()
        liberr.ErrIsNil(ctx, err, "获取数据失败")
        if one.IsEmpty() {
            liberr.ErrIsNil(ctx, errors.New("没有权限修改数据"))
        }
        _, err = m.Update(do.DemoDataAuth{
            Title:     req.Title,
            UpdatedBy: systemService.Context().GetUserId(ctx),
        })
        liberr.ErrIsNil(ctx, err, "修改失败")
    })
    return
}

此时修改了没有修改权限的数据时提示没有权限

控制删除操作权限实例如下:

修改internal/app/demo/logic/demoDataAuth/demo_data_auth.go文件Delete方法内容:

func (s *sDemoDataAuth) Delete(ctx context.Context, ids []uint) (err error) {
    err = g.Try(ctx, func(ctx context.Context) {
        //添加数据权限判断条件
        m := dao.DemoDataAuth.Ctx(ctx)
        //注意GetAuthWhere是使用创建人ID,此时若创建人转移了部门,数据会跟随创建人迁移
        //如果要保持数据保留在原部门需要使用部门ID则使用GetAuthDeptWhere
        m = systemService.SysUser().GetAuthWhere(
            ctx,
            m,
            systemService.Context().GetLoginUser(ctx),
        )
        var one gdb.Record
        for _, id := range ids {
            one, err = m.WherePri(id).One()
            liberr.ErrIsNil(ctx, err, "获取删除数据失败")
            if one.IsEmpty() {
                liberr.ErrIsNil(ctx, errors.New("没有删除改数据权限"))
            }
        }
        _, err = dao.DemoDataAuth.Ctx(ctx).Delete(dao.DemoDataAuth.Columns().Id+" in (?)", ids)
        liberr.ErrIsNil(ctx, err, "删除失败")
    })
    return
}
作者:管理员  创建时间:2024-04-30 16:09
最后编辑:管理员  更新时间:2024-06-14 15:59