更新
This commit is contained in:
1 parent
5718a00e31
commit
1850ac640e
226 files changed
+37772
-12071
No files matched your search
+140
-154
@@ -1,154 +1,140 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"server/models"
|
||||
"server/pkg/jwtutil"
|
||||
"server/services"
|
||||
authsvc "server/services/auth"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// tenantModuleItem 模块列表返回项:在模块基础信息上补充套餐开通状态,
|
||||
// locked=true 表示该模块不在当前租户已购套餐内(前端置灰并提示购买套餐)。
|
||||
type tenantModuleItem struct {
|
||||
models.SystemModules
|
||||
Locked bool `json:"locked"`
|
||||
}
|
||||
|
||||
// BackendModulesController backend 模块接口(yz_system_modules)
|
||||
type BackendModulesController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (c *BackendModulesController) backendModulesClaims() (*jwtutil.Claims, error) {
|
||||
auth := c.Ctx.Request.Header.Get("Authorization")
|
||||
if auth == "" {
|
||||
return nil, fmt.Errorf("未登录")
|
||||
}
|
||||
parts := strings.SplitN(auth, " ", 2)
|
||||
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||
return nil, fmt.Errorf("认证信息格式错误")
|
||||
}
|
||||
claims, err := jwtutil.ParseToken(parts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的token")
|
||||
}
|
||||
if claims.UserType != "backend" {
|
||||
return nil, fmt.Errorf("无权访问")
|
||||
}
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
func (c *BackendModulesController) jsonErr(httpStatus, bizCode int, msg string) {
|
||||
c.Ctx.Output.SetStatus(httpStatus)
|
||||
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
// backendUserGroupID 解析当前登录者在当前租户的角色ID。
|
||||
// claims.UserID 是认证中心 identity_id,不能直接当 yz_system_tenant_user 主键用;
|
||||
// 优先按认证绑定表(identity_id+tid → group_id,与 /auth/userinfo 同源),
|
||||
// 查不到再走业务表身份解析链(identity_id 换算 → 主键 → 老 uid)。
|
||||
func (c *BackendModulesController) backendUserGroupID(claims *jwtutil.Claims, tid uint64) uint64 {
|
||||
uid := uint64(claims.UserID)
|
||||
if uid == 0 {
|
||||
return 0
|
||||
}
|
||||
if bind, e := authsvc.GetTenantUser(uid, tid); e == nil {
|
||||
return bind.GroupID
|
||||
}
|
||||
if tu, e := findBackendTenantUser(uid, tid, false); e == nil {
|
||||
return tu.GroupID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// moduleWithEnabled 带套餐开通标记的模块输出
|
||||
type moduleWithEnabled struct {
|
||||
models.SystemModules
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// GetTenantList GET /backend/modules/getTenantList
|
||||
// 返回当前 backend 账号可见的模块(status=1 且 is_show=1),并根据租户绑定的套餐标记每个模块是否已开通。
|
||||
// 前端可据此排序(已开通在前)、置灰未开通卡片、阻止跳转。
|
||||
func (c *BackendModulesController) GetTenantList() {
|
||||
claims, err := c.backendModulesClaims()
|
||||
if err != nil {
|
||||
c.jsonErr(401, 401, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var rows []models.SystemModules
|
||||
_, err = models.Orm.QueryTable(new(models.SystemModules)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Filter("status", 1).
|
||||
Filter("is_show", 1).
|
||||
OrderBy("sort", "id").
|
||||
All(&rows)
|
||||
if err != nil {
|
||||
c.jsonErr(500, 500, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
// 租户后台是 Web 端:只保留 web 可见的模块(未配置视为全端)
|
||||
rows = services.FilterModulesByPlatform(rows, models.PlatformWeb)
|
||||
|
||||
// 查询当前租户已开通的模块 code 集合(套餐模块 + 已开通产品订单关联模块,编码已规范化)
|
||||
tid := uint64(claims.TenantId)
|
||||
allowedCodes := services.GetTenantModuleCodes(tid)
|
||||
|
||||
enhanced := make([]moduleWithEnabled, 0, len(rows))
|
||||
for _, m := range rows {
|
||||
enabled := true
|
||||
if len(allowedCodes) > 0 {
|
||||
enabled = allowedCodes[services.NormalizeModuleCode(m.Code)]
|
||||
}
|
||||
enhanced = append(enhanced, moduleWithEnabled{SystemModules: m, Enabled: enabled})
|
||||
}
|
||||
|
||||
// 角色权限过滤(与 /backend/menu/:id 同口径):
|
||||
// 未分配角色或角色 rights 为空 → 全部可见;
|
||||
// 否则仅保留「名下至少有一个被授权菜单」的模块,未授权模块直接不返回,
|
||||
// 避免首页出现可点击却进 404 的模块卡片。
|
||||
if groupID := c.backendUserGroupID(claims, tid); groupID > 0 {
|
||||
var role models.AdminRole
|
||||
if re := models.Orm.QueryTable(new(models.AdminRole)).
|
||||
Filter("id", groupID).
|
||||
Filter("cid", 2).
|
||||
One(&role); re == nil && role.Rights != nil && strings.TrimSpace(*role.Rights) != "" {
|
||||
if len(parseRightsToSet(*role.Rights)) > 0 {
|
||||
var allMenus []models.SystemMenu
|
||||
if _, me := models.Orm.QueryTable(new(models.SystemMenu)).Filter("status", 1).All(&allMenus); me == nil {
|
||||
allowedMenus := filterMenusByRights(allMenus, role.Rights)
|
||||
owningAny := services.ModuleCodesOwningMenus(rows, allMenus)
|
||||
owningAllowed := services.ModuleCodesOwningMenus(rows, allowedMenus)
|
||||
visible := make([]moduleWithEnabled, 0, len(enhanced))
|
||||
for _, item := range enhanced {
|
||||
code := services.NormalizeModuleCode(item.Code)
|
||||
// 模块名下有菜单但一个都没授权 → 隐藏;
|
||||
// 名下没有菜单(无法判定)→ 保持原行为不隐藏
|
||||
if owningAny[code] && !owningAllowed[code] {
|
||||
continue
|
||||
}
|
||||
visible = append(visible, item)
|
||||
}
|
||||
enhanced = visible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"code": 200,
|
||||
"msg": "获取成功",
|
||||
"data": map[string]interface{}{
|
||||
"list": enhanced,
|
||||
"total": len(enhanced),
|
||||
},
|
||||
}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"server/models"
|
||||
"server/pkg/identity"
|
||||
"server/pkg/jwtutil"
|
||||
"server/services"
|
||||
authsvc "server/services/auth"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// tenantModuleItem 模块列表返回项:在模块基础信息上补充套餐开通状态,
|
||||
// locked=true 表示该模块不在当前租户已购套餐内(前端置灰并提示购买套餐)。
|
||||
type tenantModuleItem struct {
|
||||
models.SystemModules
|
||||
Locked bool `json:"locked"`
|
||||
}
|
||||
|
||||
// BackendModulesController backend 模块接口(yz_system_modules)
|
||||
type BackendModulesController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (c *BackendModulesController) backendModulesClaims() (*jwtutil.Claims, error) {
|
||||
return identity.Claims(c.Ctx.Request.Header.Get("Authorization"), identity.EndBackend)
|
||||
}
|
||||
|
||||
func (c *BackendModulesController) jsonErr(httpStatus, bizCode int, msg string) {
|
||||
c.Ctx.Output.SetStatus(httpStatus)
|
||||
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
// backendUserGroupID 解析当前登录者在当前租户的角色ID。
|
||||
// claims.UserID 是认证中心 identity_id,不能直接当 yz_system_tenant_user 主键用;
|
||||
// 优先按认证绑定表(identity_id+tid → group_id,与 /auth/userinfo 同源),
|
||||
// 查不到再走业务表身份解析链(identity_id 换算 → 主键 → 老 uid)。
|
||||
func (c *BackendModulesController) backendUserGroupID(claims *jwtutil.Claims, tid uint64) uint64 {
|
||||
uid := uint64(claims.UserID)
|
||||
if uid == 0 {
|
||||
return 0
|
||||
}
|
||||
if bind, e := authsvc.GetTenantUser(uid, tid); e == nil {
|
||||
return bind.GroupID
|
||||
}
|
||||
if tu, e := findBackendTenantUser(uid, tid, false); e == nil {
|
||||
return tu.GroupID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// moduleWithEnabled 带套餐开通标记的模块输出
|
||||
type moduleWithEnabled struct {
|
||||
models.SystemModules
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// GetTenantList GET /backend/modules/getTenantList
|
||||
// 返回当前 backend 账号可见的模块(status=1 且 is_show=1),并根据租户绑定的套餐标记每个模块是否已开通。
|
||||
// 前端可据此排序(已开通在前)、置灰未开通卡片、阻止跳转。
|
||||
func (c *BackendModulesController) GetTenantList() {
|
||||
claims, err := c.backendModulesClaims()
|
||||
if err != nil {
|
||||
code := identity.Status(err)
|
||||
c.jsonErr(code, code, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var rows []models.SystemModules
|
||||
_, err = models.Orm.QueryTable(new(models.SystemModules)).
|
||||
Filter("delete_time__isnull", true).
|
||||
Filter("status", 1).
|
||||
Filter("is_show", 1).
|
||||
OrderBy("sort", "id").
|
||||
All(&rows)
|
||||
if err != nil {
|
||||
c.jsonErr(500, 500, "获取失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
// 租户后台是 Web 端:只保留 web 可见的模块(未配置视为全端)
|
||||
rows = services.FilterModulesByPlatform(rows, models.PlatformWeb)
|
||||
|
||||
// 查询当前租户已开通的模块 code 集合(套餐模块 + 已开通产品订单关联模块,编码已规范化)
|
||||
tid := uint64(claims.TenantId)
|
||||
allowedCodes := services.GetTenantModuleCodes(tid)
|
||||
|
||||
enhanced := make([]moduleWithEnabled, 0, len(rows))
|
||||
for _, m := range rows {
|
||||
enabled := true
|
||||
if len(allowedCodes) > 0 {
|
||||
enabled = allowedCodes[services.NormalizeModuleCode(m.Code)]
|
||||
}
|
||||
enhanced = append(enhanced, moduleWithEnabled{SystemModules: m, Enabled: enabled})
|
||||
}
|
||||
|
||||
// 角色权限过滤(与 /backend/menu/:id 同口径):
|
||||
// 未分配角色或角色 rights 为空 → 全部可见;
|
||||
// 否则仅保留「名下至少有一个被授权菜单」的模块,未授权模块直接不返回,
|
||||
// 避免首页出现可点击却进 404 的模块卡片。
|
||||
if groupID := c.backendUserGroupID(claims, tid); groupID > 0 {
|
||||
var role models.AdminRole
|
||||
if re := models.Orm.QueryTable(new(models.AdminRole)).
|
||||
Filter("id", groupID).
|
||||
Filter("cid", 2).
|
||||
One(&role); re == nil && role.Rights != nil && strings.TrimSpace(*role.Rights) != "" {
|
||||
if len(services.ParseMenuRights(*role.Rights)) > 0 {
|
||||
var allMenus []models.SystemMenu
|
||||
if _, me := models.Orm.QueryTable(new(models.SystemMenu)).Filter("status", 1).All(&allMenus); me == nil {
|
||||
allowedMenus := filterMenusByRights(allMenus, role.Rights)
|
||||
owningAny := services.ModuleCodesOwningMenus(rows, allMenus)
|
||||
owningAllowed := services.ModuleCodesOwningMenus(rows, allowedMenus)
|
||||
visible := make([]moduleWithEnabled, 0, len(enhanced))
|
||||
for _, item := range enhanced {
|
||||
code := services.NormalizeModuleCode(item.Code)
|
||||
// 模块名下有菜单但一个都没授权 → 隐藏;
|
||||
// 名下没有菜单(无法判定)→ 保持原行为不隐藏
|
||||
if owningAny[code] && !owningAllowed[code] {
|
||||
continue
|
||||
}
|
||||
visible = append(visible, item)
|
||||
}
|
||||
enhanced = visible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"code": 200,
|
||||
"msg": "获取成功",
|
||||
"data": map[string]interface{}{
|
||||
"list": enhanced,
|
||||
"total": len(enhanced),
|
||||
},
|
||||
}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
Reference in new issue
Block a user