package controllers import ( "encoding/json" "io" "strconv" "strings" "server/models" "server/pkg/jwtutil" beego "github.com/beego/beego/v2/server/web" ) // BackendRoleController 租户端(backend)角色管理(yz_system_admin_role, cid=2) // 角色按租户隔离:所有读写均以当前登录租户(JWT 中的 tenant_id)为边界, // 租户仅能查看/管理自己名下的角色,无法越权访问其他租户数据。 type BackendRoleController struct { beego.Controller } type backendRolePayload struct { Name string `json:"name"` Status *uint8 `json:"status"` Rights interface{} `json:"rights"` } // currentTenantID 从 Bearer Token 解析当前登录租户 ID。 // 返回 (tid, true) 表示成功;失败时已写入 401/403 响应并返回 (0, false)。 func (c *BackendRoleController) currentTenantID() (uint64, bool) { authHeader := c.Ctx.Request.Header.Get("Authorization") if authHeader == "" { c.Data["json"] = map[string]interface{}{"code": 401, "msg": "未登录"} _ = c.ServeJSON() return 0, false } authParts := strings.SplitN(authHeader, " ", 2) if len(authParts) != 2 || authParts[0] != "Bearer" { c.Data["json"] = map[string]interface{}{"code": 401, "msg": "认证信息格式错误"} _ = c.ServeJSON() return 0, false } claims, err := jwtutil.ParseToken(authParts[1]) if err != nil { c.Data["json"] = map[string]interface{}{"code": 401, "msg": "无效的token"} _ = c.ServeJSON() return 0, false } if claims.UserType != "backend" && claims.UserType != "app" { c.Data["json"] = map[string]interface{}{"code": 403, "msg": "无权访问"} _ = c.ServeJSON() return 0, false } if claims.TenantId <= 0 { c.Data["json"] = map[string]interface{}{"code": 401, "msg": "租户信息缺失"} _ = c.ServeJSON() return 0, false } return uint64(claims.TenantId), true } // GetAllRoles 获取当前租户的角色列表 // GET /backend/allRoles func (c *BackendRoleController) GetAllRoles() { tid, ok := c.currentTenantID() if !ok { return } // 懒加载补齐当前租户的默认角色(租户管理员/部门负责人/员工) models.EnsureDefaultTenantRoles(tid) var rows []models.AdminRole _, err := models.Orm.QueryTable(new(models.AdminRole)). Filter("cid", 2). Filter("tenant_id", tid). OrderBy("-id"). All(&rows) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "查询失败"} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": rows} _ = c.ServeJSON() } // GetRoleByID 获取当前租户的角色详情 // GET /backend/roles/:id func (c *BackendRoleController) GetRoleByID() { tid, ok := c.currentTenantID() if !ok { return } idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseUint(idStr, 10, 64) if id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"} _ = c.ServeJSON() return } var role models.AdminRole if err := models.Orm.QueryTable(new(models.AdminRole)). Filter("id", id). Filter("cid", 2). Filter("tenant_id", tid). One(&role); err != nil { c.Data["json"] = map[string]interface{}{"code": 404, "msg": "角色不存在"} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": role} _ = c.ServeJSON() } // CreateRole 创建当前租户的角色 // POST /backend/roles func (c *BackendRoleController) CreateRole() { tid, ok := c.currentTenantID() if !ok { return } var p backendRolePayload raw, _ := io.ReadAll(c.Ctx.Request.Body) if err := json.Unmarshal(raw, &p); err != nil { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"} _ = c.ServeJSON() return } p.Name = strings.TrimSpace(p.Name) if p.Name == "" { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "name 不能为空"} _ = c.ServeJSON() return } status := uint8(1) if p.Status != nil { status = *p.Status } rights := normalizeRights(p.Rights) // 租户端创建的角色一律标记为“自定义角色”,与系统/平台预置角色区分,并按租户隔离 role := &models.AdminRole{ TenantID: tid, Cid: 2, IsCustom: 1, Name: p.Name, Status: status, Rights: rights, } id, err := models.Orm.Insert(role) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败"} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": map[string]interface{}{"id": id}} _ = c.ServeJSON() } // UpdateRole 更新当前租户的角色 // PUT /backend/roles/:id func (c *BackendRoleController) UpdateRole() { tid, ok := c.currentTenantID() if !ok { return } idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseUint(idStr, 10, 64) if id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"} _ = c.ServeJSON() return } var p backendRolePayload raw, _ := io.ReadAll(c.Ctx.Request.Body) if err := json.Unmarshal(raw, &p); err != nil { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"} _ = c.ServeJSON() return } update := map[string]interface{}{} if strings.TrimSpace(p.Name) != "" { update["name"] = strings.TrimSpace(p.Name) } if p.Status != nil { update["status"] = *p.Status } if p.Rights != nil { update["rights"] = normalizeRights(p.Rights) } if len(update) == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无更新字段"} _ = c.ServeJSON() return } // 仅允许更新本租户名下的角色,防止越权改到其他租户 cnt, err := models.Orm.QueryTable(new(models.AdminRole)). Filter("id", id). Filter("cid", 2). Filter("tenant_id", tid). Update(update) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败"} _ = c.ServeJSON() return } if cnt == 0 { c.Data["json"] = map[string]interface{}{"code": 404, "msg": "角色不存在"} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"} _ = c.ServeJSON() } // DeleteRole 删除当前租户的角色 // DELETE /backend/roles/:id func (c *BackendRoleController) DeleteRole() { tid, ok := c.currentTenantID() if !ok { return } idStr := c.Ctx.Input.Param(":id") id, _ := strconv.ParseUint(idStr, 10, 64) if id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"} _ = c.ServeJSON() return } // 仅允许删除本租户名下的角色 cnt, err := models.Orm.QueryTable(new(models.AdminRole)). Filter("id", id). Filter("cid", 2). Filter("tenant_id", tid). Delete() if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "删除失败"} _ = c.ServeJSON() return } if cnt == 0 { c.Data["json"] = map[string]interface{}{"code": 404, "msg": "角色不存在"} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"} _ = c.ServeJSON() }