在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。
例如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制, 对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了。如设置只能看本公司、或者本部门的数据,对于特殊的领导,可能需要跨部门的数据, 因此程序不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制。
(捐赠版、授权版才有此功能)
数据权限演示
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_id
和created_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-12-03 15:05