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} // 超级管理员(9527)已拦截;其余预定义(0/1)与自定义角色均可更新显示名称 if input.RoleName != "" { 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": "删除成功"}) }