Files
web/server/handlers/role_permission.go

206 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"context"
"net/http"
"strconv"
"time"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"yh_web/server/config"
"yh_web/server/models"
"github.com/gin-gonic/gin"
)
const customRoleIDStart = 1000 // 自定义角色 role_id 从此值起
// GetRolePermissionsList 返回所有角色及其权限(含预定义与自定义)
func GetRolePermissionsList(c *gin.Context) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
coll := config.GetDB(config.DBName).Collection("role_permissions")
cursor, err := coll.Find(ctx, bson.M{})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
defer cursor.Close(ctx)
var docs []models.RolePermissionsDoc
if err = cursor.All(ctx, &docs); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
permMap := make(map[int][]string)
nameMap := make(map[int]string)
for _, d := range docs {
permMap[d.RoleID] = d.Permissions
if d.RoleName != "" {
nameMap[d.RoleID] = d.RoleName
}
}
allKeys := allPermissionKeys()
// 预定义角色固定在前9527, 0, 1再按 role_id 排自定义
predef := []int{models.RoleIDSuperAdmin, models.RoleIDSuperUser, models.RoleIDUser}
seen := make(map[int]bool)
list := make([]gin.H, 0)
for _, rid := range predef {
seen[rid] = true
perms := permMap[rid]
if perms == nil {
perms = []string{}
}
if rid == models.RoleIDSuperAdmin {
perms = allKeys
}
name := nameMap[rid]
if name == "" {
name = models.DefaultRoleNames[rid]
}
list = append(list, gin.H{
"role_id": rid,
"role_name": name,
"permissions": perms,
"is_custom": false,
})
}
for _, d := range docs {
if seen[d.RoleID] {
continue
}
seen[d.RoleID] = true
name := d.RoleName
if name == "" {
name = "角色" + strconv.Itoa(d.RoleID)
}
perms := d.Permissions
if perms == nil {
perms = []string{}
}
list = append(list, gin.H{
"role_id": d.RoleID,
"role_name": name,
"permissions": perms,
"is_custom": true,
})
}
c.JSON(http.StatusOK, gin.H{
"list": list,
"all_permissions": models.AllPermissions,
})
}
// UpdateRolePermissions 更新指定角色的权限
func UpdateRolePermissions(c *gin.Context) {
roleIDStr := c.Param("role_id")
roleID, err := strconv.Atoi(roleIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 role_id"})
return
}
if roleID == models.RoleIDSuperAdmin {
c.JSON(http.StatusBadRequest, gin.H{"error": "超级管理员权限不可修改"})
return
}
var input struct {
RoleName string `json:"role_name"`
Permissions []string `json:"permissions"`
}
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
coll := config.GetDB(config.DBName).Collection("role_permissions")
filter := bson.M{"role_id": roleID}
set := bson.M{"role_id": roleID, "permissions": input.Permissions}
if input.RoleName != "" && roleID >= customRoleIDStart {
set["role_name"] = input.RoleName
}
update := bson.M{"$set": set}
opts := options.UpdateOne().SetUpsert(true)
_, err = coll.UpdateOne(ctx, filter, update, opts)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "保存成功", "role_id": roleID, "permissions": input.Permissions})
}
// CreateRoleInput 创建角色
type CreateRoleInput struct {
RoleName string `json:"role_name" binding:"required"`
Permissions []string `json:"permissions"`
}
// CreateRole 创建自定义角色
func CreateRole(c *gin.Context) {
var input CreateRoleInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请填写角色名称"})
return
}
if input.Permissions == nil {
input.Permissions = []string{}
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
coll := config.GetDB(config.DBName).Collection("role_permissions")
cursor, _ := coll.Find(ctx, bson.M{"role_id": bson.M{"$gte": customRoleIDStart}}, options.Find().SetSort(bson.D{{Key: "role_id", Value: -1}}).SetLimit(1))
var docs []models.RolePermissionsDoc
_ = cursor.All(ctx, &docs)
cursor.Close(ctx)
nextID := customRoleIDStart
for _, d := range docs {
if d.RoleID >= customRoleIDStart {
nextID = d.RoleID + 1
break
}
}
doc := models.RolePermissionsDoc{
RoleID: nextID,
RoleName: input.RoleName,
Permissions: input.Permissions,
}
_, err := coll.InsertOne(ctx, bson.M{"role_id": doc.RoleID, "role_name": doc.RoleName, "permissions": doc.Permissions})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "创建成功", "role_id": doc.RoleID, "role_name": doc.RoleName, "permissions": doc.Permissions})
}
// DeleteRole 删除自定义角色(仅 role_id >= customRoleIDStart
func DeleteRole(c *gin.Context) {
roleIDStr := c.Param("role_id")
roleID, err := strconv.Atoi(roleIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 role_id"})
return
}
if roleID < customRoleIDStart {
c.JSON(http.StatusBadRequest, gin.H{"error": "预定义角色不可删除"})
return
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
coll := config.GetDB(config.DBName).Collection("role_permissions")
_, err = coll.DeleteOne(ctx, bson.M{"role_id": roleID})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}