93 lines
2.7 KiB
Go
93 lines
2.7 KiB
Go
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 里存的是菜单 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
|
|
}
|
|
|
|
var user models.AdminUser
|
|
if err := models.Orm.QueryTable(new(models.AdminUser)).Filter("id", userID).One(&user); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
var role models.AdminRole
|
|
if err := models.Orm.QueryTable(new(models.AdminRole)).Filter("id", user.RoleID).One(&role); err != nil {
|
|
return false, err
|
|
}
|
|
if role.Rights == nil || strings.TrimSpace(*role.Rights) == "" {
|
|
return true, nil
|
|
}
|
|
|
|
menuIDs := ParseMenuRights(*role.Rights)
|
|
if len(menuIDs) == 0 {
|
|
return false, nil
|
|
}
|
|
idList := make([]uint64, 0, len(menuIDs))
|
|
for id := range menuIDs {
|
|
idList = append(idList, id)
|
|
}
|
|
|
|
// 只有启用且未删除的菜单才能授予权限,禁用的菜单不应继续放行其权限标识
|
|
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
|
|
}
|