This commit is contained in:
hero920103 committed 2026-10-19 01:13:17 +08:00
1 parent 5718a00e31
commit 1850ac640e
226 files changed
+37772 -12071

No files matched your search

+59 -17
View File
@@ -2,13 +2,55 @@ package services
import (
"encoding/json"
"strconv"
"strings"
"server/models"
)
// ParseMenuRights 将角色 rights 解析为菜单 ID 集合(兼容 JSON 数组 / 逗号分隔)。
// 数字数组是角色保存接口 json.Marshal([]uint64) 写回的规范格式,必须支持;
// 若只按 []string 反序列化会整体失败并退化成逗号切分,
// 首尾元素会带上 [ / ] 而解析不出数字,导致第一个和最后一个菜单被静默丢弃。
func ParseMenuRights(raw string) map[uint64]bool {
set := map[uint64]bool{}
var arr []interface{}
if err := json.Unmarshal([]byte(raw), &arr); err == nil {
for _, v := range arr {
if n := menuIDOf(v); n > 0 {
set[n] = true
}
}
return set
}
for _, s := range strings.Split(raw, ",") {
if n, e := strconv.ParseUint(strings.TrimSpace(s), 10, 64); e == nil {
set[n] = true
}
}
return set
}
// menuIDOf 把 JSON 元素(数字或字符串)转成菜单 ID,无效时返回 0
func menuIDOf(v interface{}) uint64 {
switch t := v.(type) {
case float64:
if t > 0 {
return uint64(t)
}
case string:
if n, e := strconv.ParseUint(strings.TrimSpace(t), 10, 64); e == nil {
return n
}
}
return 0
}
// CheckUserPermission 校验用户是否拥有指定权限标识。
// 兼容 rights 为 JSON 数组 / 逗号分隔字符串;解析失败时默认放行,避免历史数据阻断请求。
// rights 里存的是菜单 ID 而不是权限串,必须经 yz_system_menu.permission 换算后再比对;
// 直接拿 rights 元素和权限串比永远不相等,会把本来有权限的角色全部判成无权访问。
// rights 为空(nil / 空串)视为全权限,与菜单过滤 filterMenusByRights 口径一致;
// rights 有内容却解析不出任何菜单 ID(历史脏数据)按无权限处理,不放行。
func CheckUserPermission(userID int, permission string) (bool, error) {
if permission == "" || userID <= 0 {
return true, nil
@@ -26,25 +68,25 @@ func CheckUserPermission(userID int, permission string) (bool, error) {
if role.Rights == nil || strings.TrimSpace(*role.Rights) == "" {
return true, nil
}
rightsRaw := strings.TrimSpace(*role.Rights)
// 1) JSON 数组格式
var arr []string
if err := json.Unmarshal([]byte(rightsRaw), &arr); err == nil {
for _, p := range arr {
if strings.TrimSpace(p) == permission {
return true, nil
}
}
menuIDs := ParseMenuRights(*role.Rights)
if len(menuIDs) == 0 {
return false, nil
}
// 2) 逗号分隔字符串
for _, p := range strings.Split(rightsRaw, ",") {
if strings.TrimSpace(p) == permission {
return true, nil
}
idList := make([]uint64, 0, len(menuIDs))
for id := range menuIDs {
idList = append(idList, id)
}
return false, nil
// 只有启用且未删除的菜单才能授予权限,禁用的菜单不应继续放行其权限标识
count, err := models.Orm.QueryTable(new(models.SystemMenu)).
Filter("id__in", idList).
Filter("permission", permission).
Filter("status", 1).
Filter("delete_time__isnull", true).
Count()
if err != nil {
return false, err
}
return count > 0, nil
}