签入脚本
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
|
||||
"easygoadmin/internal/consts"
|
||||
"easygoadmin/internal/dao"
|
||||
)
|
||||
|
||||
// ============================== 角色数据权限(行级过滤) ==============================
|
||||
//
|
||||
// 档位(role.data_scope,多角色在身份加载层取最宽松):
|
||||
// 1-全部 租户隔离之内不过滤
|
||||
// 2-本部门及以下 dept_id IN (自身部门 + 全部子孙部门)
|
||||
// 3-本部门 dept_id = 自身部门
|
||||
// 4-仅本人 id = 自身用户ID
|
||||
//
|
||||
// 生效范围:挂接本函数的模块其 Page/List/导出(applyFilters 链)自动生效;
|
||||
// Detail/Update/Delete 不过滤,由 permission 节点与租户隔离兜底。
|
||||
// 租户隔离、软删过滤由 dao.Ctx(hooks.ApplyCtx)先于本链注入,两层独立叠加。
|
||||
|
||||
// ApplyDataScope 数据权限过滤工厂
|
||||
//
|
||||
// 返回可挂到 ModuleSpec.DataScope 的过滤函数;deptColumn 为行上的部门列名,
|
||||
// 无部门归属的行表(如内容模块)后续可按需提供按创建人过滤的变体。
|
||||
func ApplyDataScope(deptColumn string) DataScopeFunc {
|
||||
return func(ctx context.Context, m *gdb.Model, req any) *gdb.Model {
|
||||
if dataScopeBypass(ctx) {
|
||||
return m
|
||||
}
|
||||
scope := consts.GetDataScope(ctx)
|
||||
if scope <= consts.DataScopeAll {
|
||||
return m
|
||||
}
|
||||
uid := consts.GetUserID(ctx)
|
||||
deptId := consts.GetDeptID(ctx)
|
||||
switch {
|
||||
case scope >= consts.DataScopeSelf || deptId <= 0:
|
||||
// 仅本人;未分配部门的用户挂部门档时降级为仅本人(安全兜底)
|
||||
return m.Where("id", uid)
|
||||
case scope == consts.DataScopeDept:
|
||||
return m.Where(deptColumn, deptId)
|
||||
case scope == consts.DataScopeDeptAndBelow:
|
||||
return m.WhereIn(deptColumn, deptSubtreeIds(ctx, deptId))
|
||||
}
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
||||
// dataScopeBypass 数据范围豁免判断
|
||||
// 平台级(超管)或持有超管角色编码时全量可见,与权限通配逻辑对齐
|
||||
func dataScopeBypass(ctx context.Context) bool {
|
||||
if consts.IsPlatform(ctx) {
|
||||
return true
|
||||
}
|
||||
for _, r := range consts.GetRoles(ctx) {
|
||||
if r == consts.RoleCodeSuperAdmin {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// deptSubtreeIds 收集部门自身及全部子孙部门ID
|
||||
//
|
||||
// 部门为 parent_id 树且体量小,直接全量拉取后 BFS;
|
||||
// 查询经 dao.Ctx(租户隔离+软删),后续如成热点可加短时缓存
|
||||
func deptSubtreeIds(ctx context.Context, deptId int) []int {
|
||||
rows, err := dao.Dept.Ctx(ctx).Fields("id, parent_id").All()
|
||||
if err != nil || len(rows) == 0 {
|
||||
return []int{deptId}
|
||||
}
|
||||
children := make(map[int][]int, len(rows))
|
||||
for _, r := range rows {
|
||||
pid := r["parent_id"].Int()
|
||||
children[pid] = append(children[pid], r["id"].Int())
|
||||
}
|
||||
ids := []int{deptId}
|
||||
for queue := []int{deptId}; len(queue) > 0; queue = queue[1:] {
|
||||
for _, cid := range children[queue[0]] {
|
||||
ids = append(ids, cid)
|
||||
queue = append(queue, cid)
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
Reference in New Issue
Block a user