在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。
例如对于销售,财务的数据,它们是非常敏感的,因此要求对数据权限进行控制, 对于基于集团性的应用系统而言,就更多需要控制好各自公司的数据了。如设置只能看本公司、或者本部门的数据,对于特殊的领导,可能需要跨部门的数据, 因此程序不能硬编码那个领导该访问哪些数据,需要进行后台的权限和数据权限的控制。
(捐赠版、授权版才有此功能)
数据权限演示
1、创建一个用于测试数据权限的表
CREATE TABLE `demo_data_auth` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT '' COMMENT '标题',
`created_by` bigint(10) unsigned DEFAULT '0' COMMENT '创建人',
`updated_by` bigint(10) unsigned DEFAULT '0' COMMENT '修改人',
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
`updated_at` datetime DEFAULT NULL COMMENT '修改时间',
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='数据权限测试';
2、使用代码生成相关逻辑
代码生成请参考:代码生成章节
代码生成->导入上面创建的表后设置一下生成信息:
生成后使用不同用户创建相关数据,此时还没接入数据权限
验证,我们稍后接入:
3、添加数据权限判断功能
添加数据权限需要和用户表关联查询
注意数据权限和用户相关,所以业务表里面必须带有created_by
字段,否则权限不生效。
列表页查询权限控制,修改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().As("demo").
LeftJoin("sys_user user", "demo.created_by=user.id")
if req.Id != "" {
m = m.Where("demo."+dao.DemoDataAuth.Columns().Id+" = ?", req.Id)
}
if req.Title != "" {
m = m.Where("demo."+dao.DemoDataAuth.Columns().Title+" = ?", req.Title)
}
if req.CreatedBy != "" {
m = m.Where("demo."+dao.DemoDataAuth.Columns().CreatedBy+" = ?", gconv.Uint(req.CreatedBy))
}
if len(req.DateRange) != 0 {
m = m.Where("demo."+dao.DemoDataAuth.Columns().CreatedAt+" >=? AND demo."+dao.DemoDataAuth.Columns().CreatedAt+" <=?", req.DateRange[0], req.DateRange[1])
}
//添加数据权限判断条件
var (
where g.Map
ent *entity.DemoDataAuth
//获取当前请求api接口对应的菜单
url = gstr.TrimLeft(ghttp.RequestFromCtx(ctx).Request.URL.Path, "/")
menuId uint
)
//获取菜单ID
menuId, err = systemService.SysAuthRule().GetIdByName(ctx, url)
liberr.ErrIsNil(ctx, err)
//获取用户所属角色对应的当前菜单的数据权限
where, err = systemService.SysUser().GetDataWhere(ctx,
systemService.Context().GetLoginUser(ctx),
ent,
menuId,
)
liberr.ErrIsNil(ctx, err)
m = m.Where(where) //添加条件
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 := "demo.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,
}
}
})
return
}
#修改model文件中,找到DemoDataAuthListRes结果提修改,添加查询字段表的别名:
type DemoDataAuthListRes struct {
Id uint `json:"id" dc:"" orm:"demo.id"`
Title string `json:"title" dc:"标题"`
CreatedUser *systemModel.LinkUserRes `orm:"with:id=created_by" json:"createdUser"`
CreatedBy uint `json:"createdBy" dc:"创建人" orm:"demo.created_by"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间" orm:"demo.created_at"`
}
在添加数据权限之前,可以看到后端控制台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 demo.* FROM `demo_data_auth` AS demo LEFT JOIN `sys_user` user ON (demo.created_by=user.id) WHERE ((demo.deleted_at is null) AND (user.id=31)) AND `demo`.`deleted_at` IS NULL AND `user`.`deleted_at` IS NULL ORDER BY `id` asc LIMIT 0,10
生成上面sql
语句是因为我当前登录用户数据权限是仅本人数据权限
只能查看自己添加的数据,可以看到查询条件中多了条件AND (user.id=31))
列表页面只能查询出两条数据:
修改一下数据权限为本部门及下级部门权限
修改当前登录用户部门为深圳总公司
则他应该能访问所在部门及下级部门添加的数据
列表查询数据:
生成的查询语句:
SELECT demo.* FROM `demo_data_auth` AS demo LEFT JOIN `sys_user` user ON (demo.created_by
=user.id) WHERE ((demo.deleted_at is null) AND (user.dept_id IN(103,104,105,106,107,101))) AND `demo`.`deleted_at` IS NULL AND `user`.`deleted_at` IS NULL ORDER BY `id` asc LIMIT 0,10
可以看到查询条件已改变为:AND (user.dept_id IN(103,104,105,106,107,101)))
控制修改操作权限实例如下:
修改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 (
where g.Map
ent *entity.DemoDataAuth
info *model.DemoDataAuthInfoRes
url = gstr.TrimLeft(ghttp.RequestFromCtx(ctx).Request.URL.Path, "/")
menuId uint
)
menuId, err = systemService.SysAuthRule().GetIdByName(ctx, url)
liberr.ErrIsNil(ctx, err)
where, err = systemService.SysUser().GetDataWhere(ctx,
systemService.Context().GetLoginUser(ctx),
ent,
menuId,
)
liberr.ErrIsNil(ctx, err)
info,err = s.GetById(ctx, req.Id)
liberr.ErrIsNil(ctx,err)
if info == nil{
liberr.ErrIsNil(ctx,gerror.New("要修改的数据不存在"))
}
if !systemService.SysUser().HasAccessByDataWhere(ctx,where,info.CreatedBy){
liberr.ErrIsNil(ctx,gerror.New("没有权限"))
}
_, err = dao.DemoDataAuth.Ctx(ctx).WherePri(req.Id).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) {
//添加数据权限判断条件
var (
where g.Map
ent *entity.DemoDataAuth
infos []*model.DemoDataAuthInfoRes
url = gstr.TrimLeft(ghttp.RequestFromCtx(ctx).Request.URL.Path, "/")
menuId uint
createdBys []interface{}
)
menuId, err = systemService.SysAuthRule().GetIdByName(ctx, url)
liberr.ErrIsNil(ctx, err)
where, err = systemService.SysUser().GetDataWhere(ctx,
systemService.Context().GetLoginUser(ctx),
ent,
menuId,
)
liberr.ErrIsNil(ctx, err)
err = dao.DemoDataAuth.Ctx(ctx).Where(dao.DemoDataAuth.Columns().Id+" in (?)", ids).
Fields(dao.DemoDataAuth.Columns().CreatedBy).Scan(&infos)
liberr.ErrIsNil(ctx, err)
if infos == nil {
liberr.ErrIsNil(ctx, gerror.New("要删除的数据不存在"))
}
for _, i := range infos {
createdBys = append(createdBys, i.CreatedBy)
}
if !systemService.SysUser().HasAccessByDataWhere(ctx, where, createdBys) {
liberr.ErrIsNil(ctx, gerror.New("没有权限"))
}
_, err = dao.DemoDataAuth.Ctx(ctx).Delete(dao.DemoDataAuth.Columns().Id+" in (?)", ids)
liberr.ErrIsNil(ctx, err, "删除失败")
})
return
}
最后编辑:管理员 更新时间:2024-12-03 15:05