Files
yunzerwebsiteallinone/go/controllers/backend_role.go
T

252 lines
6.9 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 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()
}