优化若干功能
This commit is contained in:
@@ -25,6 +25,92 @@ type backendRolePayload struct {
|
||||
Rights interface{} `json:"rights"`
|
||||
}
|
||||
|
||||
// parseSubmittedIDs 将前端提交的 rights 解析为菜单 ID 列表(兼容 JSON 数组 / 逗号分隔字符串)。
|
||||
func parseSubmittedIDs(v interface{}) []uint64 {
|
||||
ids := make([]uint64, 0)
|
||||
switch t := v.(type) {
|
||||
case []interface{}:
|
||||
for _, item := range t {
|
||||
switch n := item.(type) {
|
||||
case float64:
|
||||
ids = append(ids, uint64(n))
|
||||
case json.Number:
|
||||
if i, err := n.Int64(); err == nil {
|
||||
ids = append(ids, uint64(i))
|
||||
}
|
||||
case string:
|
||||
if i, err := strconv.ParseUint(strings.TrimSpace(n), 10, 64); err == nil {
|
||||
ids = append(ids, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
case []uint64:
|
||||
ids = append(ids, t...)
|
||||
case string:
|
||||
var arr []uint64
|
||||
if err := json.Unmarshal([]byte(t), &arr); err == nil {
|
||||
ids = append(ids, arr...)
|
||||
} else {
|
||||
for _, part := range strings.Split(t, ",") {
|
||||
if i, err := strconv.ParseUint(strings.TrimSpace(part), 10, 64); err == nil {
|
||||
ids = append(ids, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// loadAssignableTenantMenuIDs 返回租户端可分配菜单的 ID 集合:cid=2 且已启用且已显示。
|
||||
func loadAssignableTenantMenuIDs() map[uint64]bool {
|
||||
ids := make(map[uint64]bool)
|
||||
var menus []models.SystemMenu
|
||||
if _, err := models.Orm.QueryTable(new(models.SystemMenu)).All(&menus); err != nil {
|
||||
return ids
|
||||
}
|
||||
menus = filterMenusByView(menus, 2)
|
||||
menus = filterAssignableMenus(menus)
|
||||
for _, m := range menus {
|
||||
ids[m.ID] = true
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// sanitizeTenantRights 在服务端收敛租户角色权限:
|
||||
// 仅保留租户端(cid=2)已启用且已显示的菜单 ID,剔除平台菜单、停用菜单、隐藏菜单。
|
||||
// rights 为 nil 或空串表示全权限(与 filterMenusByRights 保持一致)。
|
||||
func sanitizeTenantRights(v interface{}) *string {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
if s, ok := v.(string); ok && strings.TrimSpace(s) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
submitted := parseSubmittedIDs(v)
|
||||
empty := "[]"
|
||||
if len(submitted) == 0 {
|
||||
return &empty
|
||||
}
|
||||
|
||||
allowed := loadAssignableTenantMenuIDs()
|
||||
kept := make([]uint64, 0, len(submitted))
|
||||
seen := make(map[uint64]bool, len(submitted))
|
||||
for _, id := range submitted {
|
||||
if id == 0 || seen[id] || !allowed[id] {
|
||||
continue
|
||||
}
|
||||
seen[id] = true
|
||||
kept = append(kept, id)
|
||||
}
|
||||
if len(kept) == 0 {
|
||||
return &empty
|
||||
}
|
||||
b, _ := json.Marshal(kept)
|
||||
s := string(b)
|
||||
return &s
|
||||
}
|
||||
|
||||
// currentTenantID 从 Bearer Token 解析当前登录租户 ID。
|
||||
// 返回 (tid, true) 表示成功;失败时已写入 401/403 响应并返回 (0, false)。
|
||||
func (c *BackendRoleController) currentTenantID() (uint64, bool) {
|
||||
@@ -137,7 +223,7 @@ func (c *BackendRoleController) CreateRole() {
|
||||
if p.Status != nil {
|
||||
status = *p.Status
|
||||
}
|
||||
rights := normalizeRights(p.Rights)
|
||||
rights := sanitizeTenantRights(p.Rights)
|
||||
// 租户端创建的角色一律标记为“自定义角色”,与系统/平台预置角色区分,并按租户隔离
|
||||
role := &models.AdminRole{
|
||||
TenantID: tid,
|
||||
@@ -188,7 +274,7 @@ func (c *BackendRoleController) UpdateRole() {
|
||||
update["status"] = *p.Status
|
||||
}
|
||||
if p.Rights != nil {
|
||||
update["rights"] = normalizeRights(p.Rights)
|
||||
update["rights"] = sanitizeTenantRights(p.Rights)
|
||||
}
|
||||
if len(update) == 0 {
|
||||
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无更新字段"}
|
||||
|
||||
Reference in New Issue
Block a user