做权限管理模块
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
)
|
||||
|
||||
// RoleMenu 角色-菜单关联表模型
|
||||
type RoleMenu struct {
|
||||
Id int `orm:"auto" json:"id"`
|
||||
RoleId int `orm:"column(role_id)" json:"role_id"`
|
||||
MenuId int `orm:"column(menu_id)" json:"menu_id"`
|
||||
CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
||||
CreateBy string `orm:"column(create_by);size(50);null" json:"create_by"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (r *RoleMenu) TableName() string {
|
||||
return "yz_role_menus"
|
||||
}
|
||||
|
||||
// RolePermission 角色权限响应结构(包含菜单信息)
|
||||
type RolePermission struct {
|
||||
RoleId int `json:"role_id"`
|
||||
RoleName string `json:"role_name"`
|
||||
MenuIds []int `json:"menu_ids"`
|
||||
Permissions []string `json:"permissions"` // 权限标识列表
|
||||
}
|
||||
|
||||
// MenuPermission 菜单权限信息
|
||||
type MenuPermission struct {
|
||||
MenuId int `json:"menu_id"`
|
||||
MenuName string `json:"menu_name"`
|
||||
Path string `json:"path"`
|
||||
MenuType int `json:"menu_type"` // 1: 页面菜单, 2: API接口
|
||||
Permission string `json:"permission"` // 权限标识
|
||||
ParentId int `json:"parent_id"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
orm.RegisterModel(new(RoleMenu))
|
||||
}
|
||||
|
||||
// GetRoleMenus 获取指定角色的所有菜单权限
|
||||
func GetRoleMenus(roleId int) ([]int, error) {
|
||||
o := orm.NewOrm()
|
||||
var menuIds []int
|
||||
|
||||
_, err := o.Raw("SELECT menu_id FROM yz_role_menus WHERE role_id = ?", roleId).QueryRows(&menuIds)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取角色菜单失败: %v", err)
|
||||
}
|
||||
|
||||
return menuIds, nil
|
||||
}
|
||||
|
||||
// GetRolePermissions 获取角色的详细权限信息(包括菜单和API权限)
|
||||
func GetRolePermissions(roleId int) (*RolePermission, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
// 获取角色信息
|
||||
var role Role
|
||||
err := o.Raw("SELECT * FROM yz_roles WHERE role_id = ? AND delete_time IS NULL", roleId).QueryRow(&role)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("角色不存在: %v", err)
|
||||
}
|
||||
|
||||
// 获取角色关联的所有菜单ID
|
||||
menuIds, err := GetRoleMenus(roleId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取权限标识列表
|
||||
var permissions []string
|
||||
if len(menuIds) > 0 {
|
||||
// 构建IN查询的占位符和参数
|
||||
placeholders := make([]string, len(menuIds))
|
||||
args := make([]interface{}, len(menuIds))
|
||||
for i, id := range menuIds {
|
||||
placeholders[i] = "?"
|
||||
args[i] = id
|
||||
}
|
||||
query := fmt.Sprintf("SELECT DISTINCT permission FROM yz_menus WHERE id IN (%s) AND permission IS NOT NULL AND permission != ''", strings.Join(placeholders, ","))
|
||||
_, err = o.Raw(query, args...).QueryRows(&permissions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取权限标识失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &RolePermission{
|
||||
RoleId: role.RoleId,
|
||||
RoleName: role.RoleName,
|
||||
MenuIds: menuIds,
|
||||
Permissions: permissions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAllMenuPermissions 获取所有菜单权限列表(用于分配权限时展示)
|
||||
func GetAllMenuPermissions() ([]*MenuPermission, error) {
|
||||
o := orm.NewOrm()
|
||||
var menus []*MenuPermission
|
||||
|
||||
_, err := o.Raw("SELECT id as menu_id, name as menu_name, path, menu_type, permission, parent_id FROM yz_menus WHERE status = 1 ORDER BY parent_id, `order`").QueryRows(&menus)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取菜单列表失败: %v", err)
|
||||
}
|
||||
|
||||
return menus, nil
|
||||
}
|
||||
|
||||
// AssignRolePermissions 为角色分配权限(菜单)
|
||||
func AssignRolePermissions(roleId int, menuIds []int, createBy string) error {
|
||||
o := orm.NewOrm()
|
||||
|
||||
// 先删除该角色的所有权限(使用更快的方式)
|
||||
_, err := o.Raw("DELETE FROM yz_role_menus WHERE role_id = ?", roleId).Exec()
|
||||
if err != nil {
|
||||
return fmt.Errorf("删除旧权限失败: %v", err)
|
||||
}
|
||||
|
||||
// 如果没有新权限,直接返回
|
||||
if len(menuIds) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 使用更高效的批量插入方式
|
||||
// 如果数据量太大,分批插入以避免超时
|
||||
batchSize := 500 // 每批500条,MySQL可以高效处理
|
||||
total := len(menuIds)
|
||||
|
||||
for i := 0; i < total; i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > total {
|
||||
end = total
|
||||
}
|
||||
|
||||
batch := menuIds[i:end]
|
||||
|
||||
// 构建批量INSERT语句
|
||||
query := "INSERT INTO yz_role_menus (role_id, menu_id, create_by) VALUES "
|
||||
values := make([]interface{}, 0, len(batch)*3)
|
||||
|
||||
placeholders := make([]string, 0, len(batch))
|
||||
for _, menuId := range batch {
|
||||
placeholders = append(placeholders, "(?, ?, ?)")
|
||||
values = append(values, roleId, menuId, createBy)
|
||||
}
|
||||
|
||||
query += strings.Join(placeholders, ", ")
|
||||
|
||||
// 执行批量插入
|
||||
_, err = o.Raw(query, values...).Exec()
|
||||
if err != nil {
|
||||
return fmt.Errorf("插入新权限失败(批次 %d/%d): %v", i/batchSize+1, (total+batchSize-1)/batchSize, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUserPermissions 获取用户的所有权限(通过用户角色)
|
||||
func GetUserPermissions(userId int) (*RolePermission, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
// 获取用户信息
|
||||
var user User
|
||||
err := o.Raw("SELECT * FROM yz_users WHERE id = ? AND delete_time IS NULL", userId).QueryRow(&user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("用户不存在: %v", err)
|
||||
}
|
||||
|
||||
// 如果用户没有角色,返回空权限
|
||||
if user.Role == 0 {
|
||||
return &RolePermission{
|
||||
RoleId: 0,
|
||||
RoleName: "无角色",
|
||||
MenuIds: []int{},
|
||||
Permissions: []string{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 获取角色权限
|
||||
return GetRolePermissions(user.Role)
|
||||
}
|
||||
|
||||
// CheckUserPermission 检查用户是否拥有指定权限
|
||||
func CheckUserPermission(userId int, permission string) (bool, error) {
|
||||
if permission == "" {
|
||||
return true, nil // 空权限标识表示不需要权限控制
|
||||
}
|
||||
|
||||
userPerms, err := GetUserPermissions(userId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 检查权限列表中是否包含指定权限
|
||||
for _, perm := range userPerms.Permissions {
|
||||
if perm == permission {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// MenuTreeNode 菜单树节点(包含子节点)
|
||||
type MenuTreeNode struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
ParentId int `json:"parent_id"`
|
||||
Icon string `json:"icon"`
|
||||
Order int `json:"order"`
|
||||
Status int8 `json:"status"`
|
||||
ComponentPath string `json:"component_path"`
|
||||
IsExternal int8 `json:"is_external"`
|
||||
ExternalUrl string `json:"external_url"`
|
||||
MenuType int8 `json:"menu_type"`
|
||||
Permission string `json:"permission"`
|
||||
Children []*MenuTreeNode `json:"children"`
|
||||
}
|
||||
|
||||
// GetUserMenuTree 获取用户有权限访问的菜单树(仅页面菜单)
|
||||
func GetUserMenuTree(userId int) ([]*MenuTreeNode, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
// 获取用户角色
|
||||
var user User
|
||||
err := o.Raw("SELECT * FROM yz_users WHERE id = ? AND delete_time IS NULL", userId).QueryRow(&user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("用户不存在: %v", err)
|
||||
}
|
||||
|
||||
if user.Role == 0 {
|
||||
return []*MenuTreeNode{}, nil
|
||||
}
|
||||
|
||||
// 获取角色的菜单ID列表
|
||||
menuIds, err := GetRoleMenus(user.Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(menuIds) == 0 {
|
||||
return []*MenuTreeNode{}, nil
|
||||
}
|
||||
|
||||
// 获取菜单信息(仅页面菜单)
|
||||
var menus []*Menu
|
||||
// 构建IN查询的占位符和参数
|
||||
placeholders := make([]string, len(menuIds))
|
||||
args := make([]interface{}, len(menuIds))
|
||||
for i, id := range menuIds {
|
||||
placeholders[i] = "?"
|
||||
args[i] = id
|
||||
}
|
||||
query := fmt.Sprintf("SELECT * FROM yz_menus WHERE id IN (%s) AND menu_type = 1 AND status = 1 ORDER BY parent_id, `order`", strings.Join(placeholders, ","))
|
||||
_, err = o.Raw(query, args...).QueryRows(&menus)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取菜单列表失败: %v", err)
|
||||
}
|
||||
|
||||
// 转换为MenuTreeNode
|
||||
var nodes []*MenuTreeNode
|
||||
for _, m := range menus {
|
||||
nodes = append(nodes, &MenuTreeNode{
|
||||
Id: m.Id,
|
||||
Name: m.Name,
|
||||
Path: m.Path,
|
||||
ParentId: m.ParentId,
|
||||
Icon: m.Icon,
|
||||
Order: m.Order,
|
||||
Status: m.Status,
|
||||
ComponentPath: m.ComponentPath,
|
||||
IsExternal: m.IsExternal,
|
||||
ExternalUrl: m.ExternalUrl,
|
||||
MenuType: m.MenuType,
|
||||
Permission: m.Permission,
|
||||
Children: []*MenuTreeNode{},
|
||||
})
|
||||
}
|
||||
|
||||
// 构建菜单树
|
||||
return buildMenuTree(nodes, 0), nil
|
||||
}
|
||||
|
||||
// buildMenuTree 构建菜单树
|
||||
func buildMenuTree(menus []*MenuTreeNode, parentId int) []*MenuTreeNode {
|
||||
var tree []*MenuTreeNode
|
||||
|
||||
for _, menu := range menus {
|
||||
if menu.ParentId == parentId {
|
||||
menu.Children = buildMenuTree(menus, menu.Id)
|
||||
tree = append(tree, menu)
|
||||
}
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user