250 lines
6.8 KiB
Go
250 lines
6.8 KiB
Go
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,
|
||
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()
|
||
}
|